From: Arto Merilainen amerilainen@nvidia.com
This patch series adds application level support for 2d hardware acceleration on Tegra SoCs.
The patch series consists of three patches: Host1x stream library, 2d library and a test application for the 2d library. The first patch introduces stream library that is used for doing buffer management, synchronization and command stream management. The second patch adds support for doing simple 2d operations (fill, copy, stretch). The third patch adds a test application for the 2d functions.
Currently, both stream and 2d libraries are placed under libdrm. The current goal is to introduce the code and move it later into its own library (or merge it to Tegra DDX).
Memory management code is not compatible with the patches Thierry sent previously. However, synchronizing the code should not be hard as they both add the same functionality.
Arto Merilainen (1): tegra: Add stream library
Francis Hart (2): tegra: Add 2d library tests: tegra: Add 2d tests
Makefile.am | 6 +- configure.ac | 14 + tegra/2d/hw_gr2d.h | 2614 ++++++++++++++++++++++++++++++++++++++++ tegra/2d/tegra_2d_api.c | 235 ++++ tegra/2d/tegra_2d_color.c | 412 +++++++ tegra/2d/tegra_2d_color.h | 51 + tegra/2d/tegra_2d_context.c | 140 +++ tegra/2d/tegra_2d_context.h | 67 + tegra/2d/tegra_2d_copy.c | 209 ++++ tegra/2d/tegra_2d_copy.h | 38 + tegra/2d/tegra_2d_fill.c | 136 +++ tegra/2d/tegra_2d_fill.h | 36 + tegra/2d/tegra_2d_frcopy.c | 274 +++++ tegra/2d/tegra_2d_frcopy.h | 85 ++ tegra/2d/tegra_2d_g2copy.c | 272 +++++ tegra/2d/tegra_2d_g2copy.h | 88 ++ tegra/2d/tegra_2d_g2fill.c | 192 +++ tegra/2d/tegra_2d_g2fill.h | 80 ++ tegra/2d/tegra_2d_reg_g2sb.h | 89 ++ tegra/2d/tegra_2d_reg_host.h | 119 ++ tegra/2d/tegra_2d_sbcopy.c | 388 ++++++ tegra/2d/tegra_2d_sbcopy.h | 94 ++ tegra/2d/tegra_2d_surface.c | 280 +++++ tegra/2d/tegra_2d_surface.h | 57 + tegra/2d/tegra_2d_util.c | 145 +++ tegra/2d/tegra_2d_util.h | 89 ++ tegra/Makefile.am | 36 + tegra/class_ids.h | 35 + tegra/host1x01_hardware.h | 122 ++ tegra/hw_host1x01_uclass.h | 143 +++ tegra/libdrm_tegra.pc.in | 10 + tegra/tegra_2d.h | 223 ++++ tegra/tegra_drm.c | 876 ++++++++++++++ tegra/tegra_drm.h | 142 +++ tegra/tegra_drmif.h | 107 ++ tests/tegra/2d/Makefile.am | 13 + tests/tegra/2d/tegra_2d_test.c | 413 +++++++ 37 files changed, 8329 insertions(+), 1 deletion(-) create mode 100644 tegra/2d/hw_gr2d.h create mode 100644 tegra/2d/tegra_2d_api.c create mode 100644 tegra/2d/tegra_2d_color.c create mode 100644 tegra/2d/tegra_2d_color.h create mode 100644 tegra/2d/tegra_2d_context.c create mode 100644 tegra/2d/tegra_2d_context.h create mode 100644 tegra/2d/tegra_2d_copy.c create mode 100644 tegra/2d/tegra_2d_copy.h create mode 100644 tegra/2d/tegra_2d_fill.c create mode 100644 tegra/2d/tegra_2d_fill.h create mode 100644 tegra/2d/tegra_2d_frcopy.c create mode 100644 tegra/2d/tegra_2d_frcopy.h create mode 100644 tegra/2d/tegra_2d_g2copy.c create mode 100644 tegra/2d/tegra_2d_g2copy.h create mode 100644 tegra/2d/tegra_2d_g2fill.c create mode 100644 tegra/2d/tegra_2d_g2fill.h create mode 100644 tegra/2d/tegra_2d_reg_g2sb.h create mode 100644 tegra/2d/tegra_2d_reg_host.h create mode 100644 tegra/2d/tegra_2d_sbcopy.c create mode 100644 tegra/2d/tegra_2d_sbcopy.h create mode 100644 tegra/2d/tegra_2d_surface.c create mode 100644 tegra/2d/tegra_2d_surface.h create mode 100644 tegra/2d/tegra_2d_util.c create mode 100644 tegra/2d/tegra_2d_util.h create mode 100644 tegra/Makefile.am create mode 100644 tegra/class_ids.h create mode 100644 tegra/host1x01_hardware.h create mode 100644 tegra/hw_host1x01_uclass.h create mode 100644 tegra/libdrm_tegra.pc.in create mode 100644 tegra/tegra_2d.h create mode 100644 tegra/tegra_drm.c create mode 100644 tegra/tegra_drm.h create mode 100644 tegra/tegra_drmif.h create mode 100644 tests/tegra/2d/Makefile.am create mode 100644 tests/tegra/2d/tegra_2d_test.c
From: Arto Merilainen amerilainen@nvidia.com
This patch introduces tegra stream library. The library is used for buffer management, command stream construction and work synchronization.
Signed-off-by: Arto Merilainen amerilainen@nvidia.com --- Makefile.am | 6 +- configure.ac | 13 + tegra/Makefile.am | 25 ++ tegra/class_ids.h | 35 ++ tegra/host1x01_hardware.h | 122 ++++++ tegra/hw_host1x01_uclass.h | 143 ++++++++ tegra/libdrm_tegra.pc.in | 10 + tegra/tegra_drm.c | 876 ++++++++++++++++++++++++++++++++++++++++++++ tegra/tegra_drm.h | 142 +++++++ tegra/tegra_drmif.h | 107 ++++++ 10 files changed, 1478 insertions(+), 1 deletion(-) create mode 100644 tegra/Makefile.am create mode 100644 tegra/class_ids.h create mode 100644 tegra/host1x01_hardware.h create mode 100644 tegra/hw_host1x01_uclass.h create mode 100644 tegra/libdrm_tegra.pc.in create mode 100644 tegra/tegra_drm.c create mode 100644 tegra/tegra_drm.h create mode 100644 tegra/tegra_drmif.h
diff --git a/Makefile.am b/Makefile.am index 8ecd9d9..e90ae43 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,7 +49,11 @@ if HAVE_EXYNOS EXYNOS_SUBDIR = exynos endif
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man +if HAVE_TEGRA +TEGRA_SUBDIR = tegra +endif + +SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(TEGRA_SUBDIR) tests include man
libdrm_la_LTLIBRARIES = libdrm.la libdrm_ladir = $(libdir) diff --git a/configure.ac b/configure.ac index 0c19929..36c55c7 100644 --- a/configure.ac +++ b/configure.ac @@ -114,6 +114,11 @@ AC_ARG_ENABLE(exynos-experimental-api, [Enable support for EXYNOS's experimental API (default: disabled)]), [EXYNOS=$enableval], [EXYNOS=no])
+AC_ARG_ENABLE(tegra, + AS_HELP_STRING([--enable-tegra], + [Enable support for tegra's API (default: disabled)]), + [TEGRA=$enableval], [TEGRA=no]) + dnl =========================================================================== dnl check compiler flags AC_DEFUN([LIBDRM_CC_TRY_FLAG], [ @@ -222,6 +227,11 @@ if test "x$EXYNOS" = xyes; then AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support]) fi
+AM_CONDITIONAL(HAVE_TEGRA, [test "x$TEGRA" = xyes]) +if test "x$TEGRA" = xyes; then + AC_DEFINE(HAVE_TEGRA, 1, [Have TEGRA support]) +fi + AC_ARG_ENABLE([cairo-tests], [AS_HELP_STRING([--enable-cairo-tests], [Enable support for Cairo rendering in tests (default: auto)])], @@ -358,6 +368,8 @@ AC_CONFIG_FILES([ omap/libdrm_omap.pc exynos/Makefile exynos/libdrm_exynos.pc + tegra/Makefile + tegra/libdrm_tegra.pc tests/Makefile tests/modeprint/Makefile tests/modetest/Makefile @@ -380,4 +392,5 @@ echo " Radeon API $RADEON" echo " Nouveau API $NOUVEAU" echo " OMAP API $OMAP" echo " EXYNOS API $EXYNOS" +echo " TEGRA API $TEGRA" echo "" diff --git a/tegra/Makefile.am b/tegra/Makefile.am new file mode 100644 index 0000000..72675e5 --- /dev/null +++ b/tegra/Makefile.am @@ -0,0 +1,25 @@ +AM_CFLAGS = \ + $(WARN_CFLAGS) \ + -I$(top_srcdir) \ + -I$(top_srcdir)/tegra \ + $(PTHREADSTUBS_CFLAGS) \ + -I$(top_srcdir)/include/drm + +libdrm_tegra_la_LTLIBRARIES = libdrm_tegra.la +libdrm_tegra_ladir = $(libdir) +libdrm_tegra_la_LDFLAGS = -version-number 1:0:0 -no-undefined +libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ + +libdrm_tegra_la_SOURCES = \ + tegra_drm.c + +libdrm_tegracommonincludedir = ${includedir}/tegra +libdrm_tegracommoninclude_HEADERS = \ + tegra_drm.h + +libdrm_tegraincludedir = ${includedir}/libdrm +libdrm_tegrainclude_HEADERS = \ + tegra_drmif.h + +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libdrm_tegra.pc diff --git a/tegra/class_ids.h b/tegra/class_ids.h new file mode 100644 index 0000000..834e291 --- /dev/null +++ b/tegra/class_ids.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 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. + * + */ + +#ifndef __NVHOST_CLASS_IDS_H +#define __NVHOST_CLASS_IDS_H + + +enum { + NV_HOST1X_CLASS_ID = 0x1, + NV_GRAPHICS_2D_CLASS_ID = 0x51, + NV_GRAPHICS_2D_SB_CLASS_ID = 0x52, +}; + +#endif /*__NVHOST_CLASS_IDS_H */ diff --git a/tegra/host1x01_hardware.h b/tegra/host1x01_hardware.h new file mode 100644 index 0000000..5f94d52 --- /dev/null +++ b/tegra/host1x01_hardware.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 NVIDIA Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Arto Merilainen amerilainen@nvidia.com + */ + +#ifndef __NVHOST_HOST1X01_HARDWARE_H +#define __NVHOST_HOST1X01_HARDWARE_H + +#include <linux/types.h> +#include "hw_host1x01_uclass.h" + +/* channel registers */ +#define NV_HOST1X_CHANNEL_MAP_SIZE_BYTES 16384 +#define NV_HOST1X_SYNC_MLOCK_NUM 16 + +/* sync registers */ +#define HOST1X_CHANNEL_SYNC_REG_BASE 0x3000 +#define NV_HOST1X_NB_MLOCKS 16 + +#define BIT(nr) (1UL << (nr)) + +static inline uint32_t nvhost_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 nvhost_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 nvhost_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 nvhost_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 nvhost_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 nvhost_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 nvhost_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 nvhost_opcode_setclass( + unsigned class_id, unsigned offset, unsigned mask) +{ + return (0 << 28) | (offset << 16) | (class_id << 6) | mask; +} +static inline uint32_t nvhost_opcode_nonincr(unsigned offset, unsigned count) +{ + return (2 << 28) | (offset << 16) | count; +} + +static inline uint32_t nvhost_opcode_mask(unsigned offset, unsigned mask) +{ + return (3 << 28) | (offset << 16) | mask; +} + +static inline uint32_t nvhost_mask2(unsigned x, unsigned y) +{ + return 1 | (1 << (y - x)); +} +#endif diff --git a/tegra/hw_host1x01_uclass.h b/tegra/hw_host1x01_uclass.h new file mode 100644 index 0000000..ba8c2d5 --- /dev/null +++ b/tegra/hw_host1x01_uclass.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 NVIDIA Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Arto Merilainen amerilainen@nvidia.com + */ + + /* + * Function naming determines intended use: + * + * <x>_r(void) : Returns the offset for register <x>. + * + * <x>_w(void) : Returns the word offset for word (4 byte) element <x>. + * + * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits. + * + * <x>_<y>_f(uint32_t v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field <y> of register <x>. This value + * can be |'d with others to produce a full register value for + * register <x>. + * + * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This + * value can be ~'d and then &'d to clear the value of field <y> for + * register <x>. + * + * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted + * to place it at field <y> of register <x>. This value can be |'d + * with others to produce a full register value for <x>. + * + * <x>_<y>_v(uint32_t r) : Returns the value of field <y> from a full register + * <x> value 'r' after being shifted to place its LSB at bit 0. + * This value is suitable for direct comparison with other unshifted + * values appropriate for use in field <y> of register <x>. + * + * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for + * field <y> of register <x>. This value is suitable for direct + * comparison with unshifted values appropriate for use in field <y> + * of register <x>. + */ + +#ifndef __hw_host1x_uclass_host1x_h__ +#define __hw_host1x_uclass_host1x_h__ + +static inline uint32_t host1x_uclass_incr_syncpt_r(void) +{ + return 0x0; +} +static inline uint32_t host1x_uclass_incr_syncpt_cond_f(uint32_t v) +{ + return (v & 0xff) << 8; +} +static inline uint32_t host1x_uclass_incr_syncpt_cond_op_done_v(void) +{ + return 1; +} +static inline uint32_t host1x_uclass_incr_syncpt_indx_f(uint32_t v) +{ + return (v & 0xff) << 0; +} +static inline uint32_t host1x_uclass_wait_syncpt_r(void) +{ + return 0x8; +} +static inline uint32_t host1x_uclass_wait_syncpt_indx_f(uint32_t v) +{ + return (v & 0xff) << 24; +} +static inline uint32_t host1x_uclass_wait_syncpt_thresh_f(uint32_t v) +{ + return (v & 0xffffff) << 0; +} +static inline uint32_t host1x_uclass_wait_syncpt_base_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_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_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 /* __hw_host1x_uclass_host1x_h__ */ diff --git a/tegra/libdrm_tegra.pc.in b/tegra/libdrm_tegra.pc.in new file mode 100644 index 0000000..3ad8c6f --- /dev/null +++ b/tegra/libdrm_tegra.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm_tegra +Description: Userspace interface to tegra kernel DRM services +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -ldrm_tegra +Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/tegra diff --git a/tegra/tegra_drm.c b/tegra/tegra_drm.c new file mode 100644 index 0000000..ad3a90e --- /dev/null +++ b/tegra/tegra_drm.c @@ -0,0 +1,876 @@ +/* + * Copyright (C) 2012 NVIDIA Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Arto Merilainen amerilainen@nvidia.com + */ + +#include <linux/errno.h> +#include <linux/types.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <assert.h> + +#include <drm.h> +#include <xf86drm.h> + +#include "tegra_drmif.h" +#include "tegra_drm.h" + +#include "class_ids.h" +#include "hw_host1x01_uclass.h" +#include "host1x01_hardware.h" + +/* + * stream library configuration + * + * NUMBER_OF_BUFFERS - Determine the number of preallocated command buffers + * RELOC_TABLE_SIZE - Maximum number of memory references in a command buffer + * BUFFER_SIZE_WORDS - Define the size of command buffers + */ + +#define NUMBER_OF_BUFFERS 4 +#define RELOC_TABLE_SIZE 128 +#define BUFFER_SIZE_WORDS 1024 + +enum tegra_stream_status { + TEGRADRM_STREAM_FREE, + TEGRADRM_STREAM_CONSTRUCT, + TEGRADRM_STREAM_READY +}; + +struct tegra_device { + int fd; +}; + +struct tegra_bo { + + struct tegra_device *dev; + + void *vaddr; + + uint32_t gem_handle; + unsigned int offset; + + uint32_t size; +}; + +struct tegra_channel { + + struct tegra_device *dev; + + uint64_t context; + + enum tegra_module_id module_id; + uint32_t default_class_id; + + uint32_t syncpt_id; +}; + +struct tegra_command_buffer { + + struct tegra_bo *mem; + + struct tegra_drm_reloc *reloc_table; + uint32_t *data; + + uint32_t cmd_ptr; + uint32_t reloc_ptr; + + uint64_t syncpt_max; + + int flushed; +}; + +struct tegra_stream { + + enum tegra_stream_status status; + + struct tegra_channel *channel; + int num_words; + int num_relocs; + uint32_t num_syncpt_incrs; + + struct tegra_command_buffer buffers[NUMBER_OF_BUFFERS]; + struct tegra_command_buffer *active_buffer; + unsigned int active_buffer_idx; + + uint32_t current_class_id; +}; + +/* + * tegra_next_buffer(stream) + * + * Move to use next command buffer. NOTE! This routine does not verify that the + * new buffer is ready to use. + */ + +static void tegra_next_buffer(struct tegra_stream *stream) +{ + stream->active_buffer_idx = (stream->active_buffer_idx + 1) % + NUMBER_OF_BUFFERS; + stream->active_buffer = &stream->buffers[stream->active_buffer_idx]; +} + +/* + * tegra_device_create(fd) + * + * Create a device "object" representing tegra drm device. The device should be + * opened using i.e. drmOpen(). If object cannot be created, NULL is returned + */ + +struct tegra_device *tegra_device_create(int fd) +{ + struct tegra_device *dev; + + if (!(dev = malloc(sizeof(dev)))) + goto err_dev_alloc; + dev->fd = fd; + + return dev; + +err_dev_alloc: + return NULL; +} + +/* + * tegra_device_destroy(dev) + * + * Remove device object created using tegra_device_create(). The caller is + * responsible for calling drmClose(). + */ + +void tegra_device_destroy(struct tegra_device *dev) +{ + if (!dev) + return; + free(dev); +} + +/* + * tegra_channel_open(dev, module_id) + * + * Reserve channel resources for given module. Host1x has several channels + * each of which is dedicated for a certain hardware module. The opened + * channel is used by streams for delivering command buffers. + */ + +struct tegra_channel *tegra_channel_open( + struct tegra_device *dev, + enum tegra_module_id module_id) +{ + struct tegra_channel *channel; + struct tegra_drm_get_channel_param_args get_args; + struct tegra_drm_open_channel_args open_args; + uint32_t default_class_id; + + if (!(channel = malloc(sizeof(*channel)))) + goto err_channel_alloc; + + switch (module_id) { + case TEGRADRM_MODULEID_2D: + default_class_id = NV_GRAPHICS_2D_CLASS_ID; + break; + default: + return NULL; + } + + channel->module_id = module_id; + channel->default_class_id = default_class_id; + + open_args.class = default_class_id; + if (drmIoctl(dev->fd, DRM_IOCTL_TEGRA_DRM_OPEN_CHANNEL, &open_args)) + goto err_channel_open; + + channel->context = open_args.context; + get_args.context = open_args.context; + get_args.param = 0; + + if (drmIoctl(dev->fd, DRM_IOCTL_TEGRA_DRM_GET_SYNCPOINT, + &get_args)) + goto err_tegra_ioctl; + channel->syncpt_id = get_args.value; + + channel->dev = dev; + + return channel; + +err_tegra_ioctl: + drmIoctl(dev->fd, DRM_IOCTL_TEGRA_DRM_CLOSE_CHANNEL, &open_args); +err_channel_open: + free(channel); +err_channel_alloc: + return NULL; +} + +/* + * tegra_channel_close(channel) + * + * Close a channel. + */ + +void tegra_channel_close(struct tegra_channel *channel) +{ + struct tegra_drm_open_channel_args close_args; + + if (!channel) + return; + + close_args.class = channel->default_class_id; + close_args.context = channel->context; + + drmIoctl(channel->dev->fd, DRM_IOCTL_TEGRA_DRM_CLOSE_CHANNEL, + &close_args); + + free(channel); +} + +/* + * tegra_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 + * tegra_stream_push*(). + */ + +struct tegra_stream *tegra_stream_create( + struct tegra_channel *channel) +{ + struct tegra_stream *stream; + int i; + + if (!channel) + goto err_bad_channel; + + if (!(stream = malloc(sizeof(*stream)))) + goto err_alloc_stream; + + memset(stream, '\0', sizeof(*stream)); + stream->channel = channel; + stream->status = TEGRADRM_STREAM_FREE; + + for (i = 0; i < NUMBER_OF_BUFFERS; i++) { + struct tegra_command_buffer *buffer = &stream->buffers[i]; + + if (!(buffer->mem = tegra_bo_allocate(stream->channel->dev, + sizeof(uint32_t) * BUFFER_SIZE_WORDS, 4))) + goto err_buffer_create; + + if(!(buffer->data = tegra_bo_map(buffer->mem))) + goto err_buffer_create; + + if (!(buffer->reloc_table = + malloc(RELOC_TABLE_SIZE * sizeof(struct tegra_drm_reloc)))) + goto err_buffer_create; + + buffer->reloc_ptr = 0; + buffer->cmd_ptr = 0; + } + + stream->active_buffer_idx = 0; + stream->active_buffer = &stream->buffers[0]; + + return stream; + +err_buffer_create: + for (i = 0; i < NUMBER_OF_BUFFERS; i++) { + free(stream->buffers[i].reloc_table); + tegra_bo_free(stream->buffers[i].mem); + } + free(stream); +err_alloc_stream: +err_bad_channel: + return NULL; +} + +/* + * tegra_stream_destroy(stream) + * + * Destroy the given stream object. All resrouces are released. + */ + +void tegra_stream_destroy(struct tegra_stream *stream) +{ + int i; + + if (!stream) + return; + + for (i = 0; i < NUMBER_OF_BUFFERS; i++) { + free(stream->buffers[i].reloc_table); + tegra_bo_free(stream->buffers[i].mem); + } + + free(stream); +} + +/* + * tegra_fence_is_valid(fence) + * + * Check validity of a fence. We just check that the fence range + * is valid w.r.t. host1x hardware. + */ + +int tegra_fence_is_valid(const struct tegra_fence *fence) +{ + int valid = fence ? 1 : 0; + valid = valid && fence->id != (uint32_t) -1; + valid = valid && fence->id < 32; + return valid; +} + +/* + * tegra_fence_clear(fence) + * + * Clear (=invalidate) given fence + */ + +void tegra_fence_clear(struct tegra_fence *fence) +{ + fence->id = (uint32_t) -1; + fence->value = 0; +} + +/* + * tegra_fence_copy(dst, src) + * + * Copy fence + */ + +void tegra_fence_copy(struct tegra_fence *dst, const struct tegra_fence *src) +{ + *dst = *src; +} + +/* + * tegra_fence_waitex(channel, fence, timeout, value) + * + * Wait for a given syncpoint value with timeout. The end value is returned in + * "value" variable. The function returns 0 if the syncpoint value was + * reached before timeout, otherwise an error code. + */ + +int tegra_fence_waitex(struct tegra_channel *channel, + struct tegra_fence *fence, + long timeout, + long *value) +{ + struct tegra_drm_syncpt_wait_args args; + int err; + + if (!tegra_fence_is_valid(fence)) + return -EINVAL; + + args.timeout = timeout; + args.id = fence->id; + args.thresh = fence->value; + + err = drmIoctl(channel->dev->fd, DRM_IOCTL_TEGRA_DRM_SYNCPT_WAIT, &args); + + if (value) + *value = args.value; + + return err; +} + +/* + * tegra_fence_wait_timeout(channel, fence, timeout) + * + * Wait for a given syncpoint value with timeout. The function returns 0 if + * the syncpoint value was reached before timeout, otherwise an error code. + */ + +int tegra_fence_wait_timeout(struct tegra_channel *channel, + struct tegra_fence *fence, + long timeout) +{ + return tegra_fence_waitex(channel, fence, timeout, NULL); +} + +/* + * tegra_fence_wait(channel, wait) + * + * Wait for a given syncpoint value without timeout. + */ + +int tegra_fence_wait(struct tegra_channel *channel, + struct tegra_fence *fence) +{ + return tegra_fence_waitex(channel, fence, DRM_TEGRA_NO_TIMEOUT, NULL); +} + +/* + * tegra_stream_push_reloc(stream, h, offset) + * + * Push a memory reference to the stream. + */ + +void tegra_stream_push_reloc(struct tegra_stream *stream, + struct tegra_bo *h, + int offset) +{ + struct tegra_drm_reloc reloc; + + if (!stream || !h) + return; + + reloc.cmdbuf_mem = stream->active_buffer->mem->gem_handle; + reloc.cmdbuf_offset = stream->active_buffer->cmd_ptr * 4; + reloc.target = h->gem_handle; + reloc.target_offset = offset; + reloc.shift = 0; + + stream->num_words--; + stream->num_relocs--; + assert(stream->num_words >= 0); + assert(stream->status == TEGRADRM_STREAM_CONSTRUCT); + stream->active_buffer->data[stream->active_buffer->cmd_ptr++] = 0xDEADBEEF; + stream->active_buffer->reloc_table[stream->active_buffer->reloc_ptr++] = + reloc; +} + +/* + * tegra_bo_gethandle(h) + * + * Get drm memory handle. This is required if the object is used as a + * framebuffer. + */ + +uint32_t tegra_bo_gethandle(struct tegra_bo *h) +{ + return h->gem_handle; +} + +/* + * tegra_bo_allocate(dev, num_bytes, alignment) + * + * Allocate num_bytes for host1x device operations. The memory is not + * automatically mapped for the application. + */ + +struct tegra_bo *tegra_bo_allocate(struct tegra_device *dev, + uint32_t num_bytes, + uint32_t alignment) +{ + struct tegra_gem_create create; + struct tegra_bo *h; + + if (!(h = malloc(sizeof(*h)))) + goto err_alloc_memory_handle; + + /* Allocate memory */ + memset(&create, 0, sizeof(create)); + create.size = num_bytes; + if (drmIoctl(dev->fd, DRM_IOCTL_TEGRA_GEM_CREATE, &create)) + goto err_alloc_memory; + + h->gem_handle = create.handle; + h->size = create.size; + h->offset = create.offset; + h->vaddr = NULL; + h->dev = dev; + + return h; + +err_alloc_memory: + free(h); +err_alloc_memory_handle: + return NULL; +} + +/* + * tegra_bo_free(h) + * + * Release given memory handle. Memory is unmapped if it is mapped. Kernel + * takes care of reference counting, so the memory area will not be freed + * unless the kernel actually has finished using the area. + */ + +void tegra_bo_free(struct tegra_bo * h) +{ + struct drm_gem_close unref; + + if (!h) + return; + + tegra_bo_unmap(h); + unref.handle = h->gem_handle; + drmIoctl(h->dev->fd, DRM_IOCTL_GEM_CLOSE, &unref); + free(h); +} + +/* + * tegra_bo_map(h) + * + * Map the given handle for the application. + */ + +void * tegra_bo_map(struct tegra_bo * h) +{ + if (!h->vaddr) { + h->vaddr = mmap(NULL, h->size, PROT_READ | PROT_WRITE, + MAP_SHARED, h->dev->fd, h->offset); + } + + return h->vaddr; +} + +/* + * tegra_bo_unmap(h) + * + * Unmap memory from the application. The contents of the memory region is + * automatically flushed to the memory + */ + +void tegra_bo_unmap(struct tegra_bo * h) +{ + if (!(h && h->vaddr)) + return; + + munmap(h->vaddr, h->size); + h->vaddr = NULL; +} + +/* + * tegra_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 tegra_stream_flush(struct tegra_stream *stream, + struct tegra_fence *fence) +{ + struct tegra_channel *ch = stream->channel; + struct tegra_drm_cmdbuf cmdbuf; + struct tegra_drm_submit_args submit; + struct tegra_drm_syncpt_incr syncpt_incr; + struct tegra_command_buffer * buffer = stream->active_buffer; + int err; + + if (!stream) + return -EINVAL; + + /* Reflushing is fine */ + if (stream->status == TEGRADRM_STREAM_FREE) + return 0; + + /* Crash if stream is constructed badly */ + assert(stream->status == TEGRADRM_STREAM_READY); + + /* Clean args */ + memset(&submit, 0, sizeof(submit)); + + /* Construct cmd buffer */ + cmdbuf.mem = buffer->mem->gem_handle; + cmdbuf.offset = 0; + cmdbuf.words = buffer->cmd_ptr; + + /* Construct syncpoint increments struct */ + syncpt_incr.syncpt_id = ch->syncpt_id; + syncpt_incr.syncpt_incrs = stream->num_syncpt_incrs; + + /* Create submit */ + submit.context = ch->context; + submit.submit_version = 1; + submit.num_relocs = buffer->reloc_ptr; + submit.num_syncpt_incrs = 1; + submit.num_cmdbufs = 1; + submit.relocs = (uint32_t)buffer->reloc_table; + submit.syncpt_incrs = (uint32_t)&syncpt_incr; + submit.cmdbufs = (uint32_t)&cmdbuf; + + /* Push submits to the channel */ + if ((err = drmIoctl(ch->dev->fd, DRM_IOCTL_TEGRA_DRM_SUBMIT, &submit))) { + tegra_fence_clear(fence); + return err; + } + + /* Return fence */ + if (fence) { + fence->id = ch->syncpt_id; + fence->value = submit.fence; + } + + stream->num_syncpt_incrs = 0; + stream->active_buffer->syncpt_max = submit.fence; + stream->active_buffer->flushed = 1; + tegra_next_buffer(stream); + + stream->status = TEGRADRM_STREAM_FREE; + return 0; +} + +/* + * tegra_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_syncpt_incrs indicate the number of syncpoint increments the stream + * is doing. + * - 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 tegra_stream_begin(struct tegra_stream *stream, + uint32_t num_words, + struct tegra_fence *fence, + uint32_t num_fences, + uint32_t num_syncpt_incrs, + uint32_t num_relocs, + uint32_t class_id) +{ + if (!stream) + return -EINVAL; + + assert(stream->status == TEGRADRM_STREAM_FREE || + stream->status == TEGRADRM_STREAM_READY); + + /* handle class id */ + if (!class_id && stream->channel->default_class_id) + class_id = stream->channel->default_class_id; + + /* include following in num words: + * - fence waits in the beginningi ( 1 + num_fences) + * - setclass in the beginning (1 word) + * - syncpoint increment at the end of the stream (2 words) + */ + + num_words += 2; + num_words += class_id ? 1 : 0; + num_words += num_fences ? 1 + num_fences : 0; + + if (num_words + num_relocs > BUFFER_SIZE_WORDS || + num_relocs > RELOC_TABLE_SIZE) + return -EINVAL; + + if ((stream->active_buffer->cmd_ptr + num_words + num_relocs > + BUFFER_SIZE_WORDS) || + (stream->active_buffer->reloc_ptr + num_relocs > RELOC_TABLE_SIZE)) { + tegra_stream_flush(stream, NULL); + } + + /* If we are about to start using a new buffer, make sure it is + * actually free */ + + if (stream->active_buffer->flushed) { + struct tegra_fence fence; + + fence.id = stream->channel->syncpt_id; + fence.value = stream->active_buffer->syncpt_max; + tegra_fence_wait(stream->channel, &fence); + + stream->active_buffer->cmd_ptr = 0; + stream->active_buffer->reloc_ptr = 0; + stream->active_buffer->flushed = 0; + } + + stream->status = TEGRADRM_STREAM_CONSTRUCT; + stream->current_class_id = class_id; + stream->num_relocs = num_relocs; + stream->num_words = num_words; + stream->num_syncpt_incrs += num_syncpt_incrs; + + /* Add fences */ + if (num_fences) { + + tegra_stream_push(stream, + nvhost_opcode_setclass(NV_HOST1X_CLASS_ID, + host1x_uclass_wait_syncpt_r(), num_fences)); + + for (; num_fences; num_fences--, fence++) { + assert(tegra_fence_is_valid(fence)); + + tegra_stream_push(stream, nvhost_class_host_wait_syncpt(fence->id, + fence->value)); + } + } + + if (class_id) + tegra_stream_push(stream, nvhost_opcode_setclass(class_id, 0, 0)); + + return 0; +} + +/* + * tegra_stream_push_setclass(stream, class_id) + * + * Push "set class" opcode to the stream. Do nothing if the class is already + * active + */ + +void tegra_stream_push_setclass(struct tegra_stream *stream, + uint32_t class_id) +{ + if (stream->current_class_id == class_id) + return; + + tegra_stream_push(stream, nvhost_opcode_setclass(class_id, 0, 0)); + stream->current_class_id = class_id; +} + +/* + * tegra_stream_end(stream) + * + * Mark end of stream. This function pushes last syncpoint increment for + * marking end of stream. + */ + +int tegra_stream_end(struct tegra_stream *stream) +{ + if (!stream) + return -EINVAL; + + /* Add last syncpoint increment on OP_DONE */ + tegra_stream_push(stream, nvhost_opcode_nonincr(0, 1)); + tegra_stream_push(stream, nvhost_class_host_incr_syncpt( + host1x_uclass_incr_syncpt_cond_op_done_v(), + stream->channel->syncpt_id)); + stream->num_syncpt_incrs += 1; + + assert(stream->status == TEGRADRM_STREAM_CONSTRUCT); + stream->status = TEGRADRM_STREAM_READY; + return 0; +} + +/* + * tegra_stream_push(stream, word) + * + * Push a single word to given stream. + */ + +void tegra_stream_push(struct tegra_stream *stream, int word) +{ + if (!stream) + return; + + stream->num_words--; + assert(stream->num_words >= 0); + assert(stream->status == TEGRADRM_STREAM_CONSTRUCT); + stream->active_buffer->data[stream->active_buffer->cmd_ptr++] = word; +} + +/* + * tegra_channel_syncpt(channel) + * + * Get channel syncpoint + */ + +int tegra_channel_syncpt(struct tegra_channel *channel) +{ + if (!channel) + return -EINVAL; + + return channel->syncpt_id; +} + +/* + * tegra_reloc (variable, handle, offset) + * + * This function creates a reloc allocation. The function should be used in + * conjunction with tegra_stream_push_words. + */ + +struct tegra_reloc tegra_reloc(const void *var, + const struct tegra_bo *h, + const uint32_t offset) +{ + struct tegra_reloc reloc = {var, (struct tegra_bo *)h, offset}; + return reloc; + +} + +/* + * tegra_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 tegra_reloc + * function. + */ + +void tegra_stream_push_words(struct tegra_stream *stream, + const void *addr, uint32_t words, + uint32_t num_relocs, ...) +{ + va_list ap; + struct tegra_reloc reloc_arg; + struct tegra_command_buffer *buffer; + + if (!stream) + return; + + buffer = stream->active_buffer; + + stream->num_words -= words; + stream->num_relocs -= num_relocs; + assert(stream->num_words >= 0 && stream->num_relocs >= 0); + assert(stream->status == TEGRADRM_STREAM_CONSTRUCT); + + /* Copy the contents */ + memcpy(buffer->data + buffer->cmd_ptr, addr, + words * sizeof(uint32_t)); + + /* Copy relocs */ + va_start(ap, num_relocs); + for (; num_relocs; num_relocs--) { + + uint32_t cmd_ptr; + struct tegra_drm_reloc reloc_entry; + + reloc_arg = va_arg(ap, struct tegra_reloc); + + cmd_ptr = buffer->cmd_ptr + + ((uint32_t *) reloc_arg.addr) - ((uint32_t *) addr); + + reloc_entry.cmdbuf_mem = buffer->mem->gem_handle; + reloc_entry.cmdbuf_offset = cmd_ptr * 4; + reloc_entry.target = reloc_arg.h->gem_handle; + reloc_entry.target_offset = reloc_arg.offset; + reloc_entry.shift = 0; + + buffer->data[cmd_ptr] = 0xDEADBEEF; + buffer->reloc_table[buffer->reloc_ptr++] = reloc_entry; + } + va_end(ap); + + buffer->cmd_ptr += words; +} diff --git a/tegra/tegra_drm.h b/tegra/tegra_drm.h new file mode 100644 index 0000000..358a2fd --- /dev/null +++ b/tegra/tegra_drm.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2012 NVIDIA Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Arto Merilainen amerilainen@nvidia.com + */ + +#ifndef _TEGRA_DRM_H_ +#define _TEGRA_DRM_H_ + +struct tegra_gem_create { + __u64 size; + unsigned int flags; + unsigned int handle; + unsigned int offset; +}; + +struct tegra_gem_invalidate { + unsigned int handle; +}; + +struct tegra_gem_flush { + unsigned int handle; +}; + +struct tegra_drm_syncpt_read_args { + __u32 id; + __u32 value; +}; + +struct tegra_drm_syncpt_incr_args { + __u32 id; + __u32 pad; +}; + +struct tegra_drm_syncpt_wait_args { + __u32 id; + __u32 thresh; + __s32 timeout; + __u32 value; +}; + +#define DRM_TEGRA_NO_TIMEOUT (-1) + +struct tegra_drm_open_channel_args { + __u32 class; + __u32 pad; + __u64 context; +}; + +struct tegra_drm_get_channel_param_args { + __u64 context; + __u32 param; + __u32 value; +}; + +struct tegra_drm_syncpt_incr { + __u32 syncpt_id; + __u32 syncpt_incrs; +}; + +struct tegra_drm_cmdbuf { + __u32 mem; + __u32 offset; + __u32 words; +}; + +struct tegra_drm_reloc { + __u32 cmdbuf_mem; + __u32 cmdbuf_offset; + __u32 target; + __u32 target_offset; + __u32 shift; + __u32 pad; +}; + +struct tegra_drm_waitchk { + __u32 mem; + __u32 offset; + __u32 syncpt_id; + __u32 thresh; +}; + +struct tegra_drm_submit_args { + __u64 context; + __u32 num_syncpt_incrs; + __u32 num_cmdbufs; + __u32 num_relocs; + __u32 submit_version; + __u32 num_waitchks; + __u32 waitchk_mask; + __u32 timeout; + __u32 pad; + __u64 syncpt_incrs; + __u64 cmdbufs; + __u64 relocs; + __u64 waitchks; + __u32 fence; /* Return value */ + + __u32 reserved[5]; /* future expansion */ +}; + +#define DRM_TEGRA_GEM_CREATE 0x00 +#define DRM_TEGRA_DRM_SYNCPT_READ 0x01 +#define DRM_TEGRA_DRM_SYNCPT_INCR 0x02 +#define DRM_TEGRA_DRM_SYNCPT_WAIT 0x03 +#define DRM_TEGRA_DRM_OPEN_CHANNEL 0x04 +#define DRM_TEGRA_DRM_CLOSE_CHANNEL 0x05 +#define DRM_TEGRA_DRM_GET_SYNCPOINT 0x06 +#define DRM_TEGRA_DRM_GET_MODMUTEXES 0x07 +#define DRM_TEGRA_DRM_SUBMIT 0x08 + +#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct tegra_gem_create) +#define DRM_IOCTL_TEGRA_DRM_SYNCPT_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_SYNCPT_READ, struct tegra_drm_syncpt_read_args) +#define DRM_IOCTL_TEGRA_DRM_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_SYNCPT_INCR, struct tegra_drm_syncpt_incr_args) +#define DRM_IOCTL_TEGRA_DRM_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_SYNCPT_WAIT, struct tegra_drm_syncpt_wait_args) +#define DRM_IOCTL_TEGRA_DRM_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_OPEN_CHANNEL, struct tegra_drm_open_channel_args) +#define DRM_IOCTL_TEGRA_DRM_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_CLOSE_CHANNEL, struct tegra_drm_open_channel_args) +#define DRM_IOCTL_TEGRA_DRM_GET_SYNCPOINT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_GET_SYNCPOINT, struct tegra_drm_get_channel_param_args) +#define DRM_IOCTL_TEGRA_DRM_GET_MODMUTEXES DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_GET_MODMUTEXES, struct tegra_drm_get_channel_param_args) +#define DRM_IOCTL_TEGRA_DRM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_DRM_SUBMIT, struct tegra_drm_submit_args) + +#endif diff --git a/tegra/tegra_drmif.h b/tegra/tegra_drmif.h new file mode 100644 index 0000000..b3f6872 --- /dev/null +++ b/tegra/tegra_drmif.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 NVIDIA Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Arto Merilainen amerilainen@nvidia.com + */ + +#ifndef TEGRA_DRMIF_H +#define TEGRA_DRMIF_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct tegra_channel; +struct tegra_bo; +struct tegra_stream; +struct tegra_device; + +struct tegra_fence { + uint32_t id; + uint32_t value; +}; + +struct tegra_reloc { + const void *addr; + struct tegra_bo *h; + uint32_t offset; +}; + +enum tegra_module_id { + TEGRADRM_MODULEID_2D +}; + +/* Device operations */ +struct tegra_device *tegra_device_create(int fd); +void tegra_device_destroy(struct tegra_device *dev); + +/* Memory operations */ +uint32_t tegra_bo_gethandle(struct tegra_bo *h); +struct tegra_bo *tegra_bo_allocate(struct tegra_device *dev, + uint32_t num_bytes, uint32_t alignment); +void tegra_bo_free(struct tegra_bo * h); +void * tegra_bo_map(struct tegra_bo * h); +void tegra_bo_unmap(struct tegra_bo * h); + +/* Channel operations */ +struct tegra_channel *tegra_channel_open(struct tegra_device *dev, + enum tegra_module_id module_id); +void tegra_channel_close(struct tegra_channel *channel); +int tegra_channel_syncpt(struct tegra_channel *channel); + +/* Stream operations */ +struct tegra_stream *tegra_stream_create(struct tegra_channel *channel); +void tegra_stream_destroy(struct tegra_stream *stream); +int tegra_stream_begin(struct tegra_stream *stream, uint32_t num_words, + struct tegra_fence *fence, uint32_t num_fences, + uint32_t num_syncpt_incrs, uint32_t num_relocs, + uint32_t class_id); +int tegra_stream_end(struct tegra_stream *stream); +int tegra_stream_flush(struct tegra_stream *stream, struct tegra_fence *fence); +void tegra_stream_push(struct tegra_stream *stream, int word); +void tegra_stream_push_setclass(struct tegra_stream *stream, + uint32_t class_id); +void tegra_stream_push_reloc(struct tegra_stream *stream, struct tegra_bo *h, + int offset); +struct tegra_reloc tegra_reloc(const void *var, const struct tegra_bo *h, + const uint32_t offset); +void tegra_stream_push_words(struct tegra_stream *stream, const void *addr, + uint32_t words, uint32_t num_relocs, ...); + +/* Fence operations */ +int tegra_fence_wait(struct tegra_channel *channel, struct tegra_fence *fence); +int tegra_fence_wait_timeout(struct tegra_channel *channel, + struct tegra_fence *fence, long timeout); +int tegra_fence_waitex(struct tegra_channel *channel, struct tegra_fence *fence, + long timeout, long *value); +int tegra_fence_is_valid(const struct tegra_fence *fence); +void tegra_fence_clear(struct tegra_fence *fence); +void tegra_fence_copy(struct tegra_fence *dst, const struct tegra_fence *src); + +#ifdef __cplusplus +}; +#endif + +#endif /* TEGRA_DRMIF_H */
I just skimmed the code of libdrm while I'm trying to understand the host1x driver. So below is what I found.
Mark On 12/13/2012 10:01 PM, Arto Meriläinen wrote:
From: Arto Merilainen amerilainen@nvidia.com
This patch introduces tegra stream library. The library is used for buffer management, command stream construction and work synchronization.
[...]
+/*
- tegra_fence_is_valid(fence)
- Check validity of a fence. We just check that the fence range
- is valid w.r.t. host1x hardware.
- */
+int tegra_fence_is_valid(const struct tegra_fence *fence) +{
- int valid = fence ? 1 : 0;
- valid = valid && fence->id != (uint32_t) -1;
- valid = valid && fence->id < 32;
Hardcode here. Assume always has 32 syncpts. Change to a micro wrapped with tegra version ifdef will be better.
- return valid;
+}
[...]
- /* Add fences */
- if (num_fences) {
tegra_stream_push(stream,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_wait_syncpt_r(), num_fences));
for (; num_fences; num_fences--, fence++) {
assert(tegra_fence_is_valid(fence));
This is useless. We already add "1 + num_fences" to num_words above. So move this "assert" before adding "1 + num_fences" to num_words makes sense.
tegra_stream_push(stream, nvhost_class_host_wait_syncpt(fence->id,
fence->value));
}
- }
- if (class_id)
tegra_stream_push(stream, nvhost_opcode_setclass(class_id, 0, 0));
- return 0;
+}
[...]
+#endif /* TEGRA_DRMIF_H */
On 12/28/2012 08:47 AM, Mark Zhang wrote:
+int tegra_fence_is_valid(const struct tegra_fence *fence) +{
- int valid = fence ? 1 : 0;
- valid = valid && fence->id != (uint32_t) -1;
- valid = valid && fence->id < 32;
Hardcode here. Assume always has 32 syncpts. Change to a micro wrapped with tegra version ifdef will be better.
You are correct. I will fix this.
- return valid;
+}
[...]
- /* Add fences */
- if (num_fences) {
tegra_stream_push(stream,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_wait_syncpt_r(), num_fences));
for (; num_fences; num_fences--, fence++) {
assert(tegra_fence_is_valid(fence));
This is useless. We already add "1 + num_fences" to num_words above. So move this "assert" before adding "1 + num_fences" to num_words makes sense.
The assertion checks the validity of a single fence - not if there is room in the command buffer.
The goal is to prevent having invalid fences in the command stream. If this check were not here it would be possible to initialise a fence with tegra_fence_clear() and put that fence into the stream.
tegra_stream_push(stream, nvhost_class_host_wait_syncpt(fence->id,
fence->value));
}
- }
- if (class_id)
tegra_stream_push(stream, nvhost_opcode_setclass(class_id, 0, 0));
- return 0;
+}
[...]
+#endif /* TEGRA_DRMIF_H */
- Arto
On 12/28/2012 03:45 PM, Arto Merilainen wrote:
On 12/28/2012 08:47 AM, Mark Zhang wrote:
+int tegra_fence_is_valid(const struct tegra_fence *fence) +{
- int valid = fence ? 1 : 0;
- valid = valid && fence->id != (uint32_t) -1;
- valid = valid && fence->id < 32;
Hardcode here. Assume always has 32 syncpts. Change to a micro wrapped with tegra version ifdef will be better.
You are correct. I will fix this.
- return valid;
+}
[...]
- /* Add fences */
- if (num_fences) {
tegra_stream_push(stream,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_wait_syncpt_r(), num_fences));
for (; num_fences; num_fences--, fence++) {
assert(tegra_fence_is_valid(fence));
This is useless. We already add "1 + num_fences" to num_words above. So move this "assert" before adding "1 + num_fences" to num_words makes sense.
The assertion checks the validity of a single fence - not if there is room in the command buffer.
The goal is to prevent having invalid fences in the command stream. If this check were not here it would be possible to initialise a fence with tegra_fence_clear() and put that fence into the stream.
My idea is, if one fence is invalid, then we should not count this in "num_words". In current code, if one fence is invalid, then this fence will not be pushed into the command stream, and the "num_words" shows a wrong command buffer size.
So I think we should: - validate the fences, remove the invalid fence - update num_words - then you don't need to check fence here - I mean, before push a host1x syncpt wait command into the active buffer of stream.
tegra_stream_push(stream,
nvhost_class_host_wait_syncpt(fence->id,
fence->value));
}
- }
- if (class_id)
tegra_stream_push(stream, nvhost_opcode_setclass(class_id,
0, 0));
- return 0;
+}
[...]
+#endif /* TEGRA_DRMIF_H */
- Arto
On 12/28/2012 09:57 AM, Mark Zhang wrote:
On 12/28/2012 03:45 PM, Arto Merilainen wrote:
On 12/28/2012 08:47 AM, Mark Zhang wrote:
- /* Add fences */
- if (num_fences) {
tegra_stream_push(stream,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_wait_syncpt_r(), num_fences));
for (; num_fences; num_fences--, fence++) {
assert(tegra_fence_is_valid(fence));
This is useless. We already add "1 + num_fences" to num_words above. So move this "assert" before adding "1 + num_fences" to num_words makes sense.
The assertion checks the validity of a single fence - not if there is room in the command buffer.
The goal is to prevent having invalid fences in the command stream. If this check were not here it would be possible to initialise a fence with tegra_fence_clear() and put that fence into the stream.
My idea is, if one fence is invalid, then we should not count this in "num_words". In current code, if one fence is invalid, then this fence will not be pushed into the command stream, and the "num_words" shows a wrong command buffer size.
So I think we should:
- validate the fences, remove the invalid fence
- update num_words
- then you don't need to check fence here - I mean, before push a host1x
syncpt wait command into the active buffer of stream.
In my opinion asking tegra_stream_begin() to put a bad fence into the stream is a case we should never be. assert() kills the application immediately (in debug builds) and usually this helps the programmer for 1) finding bugs 2) not doing bad code.
"Silencing" is not a good solution especially in this case: tegra_stream_flush() returns an invalid fence when flushing fails. If the application chains submits (i.e. do a blit and then do another using the output of the first blit) it is crucial to be sure the first submit has been performed before starting the second one.
- Arto
On 12/28/2012 04:50 PM, Arto Merilainen wrote:
On 12/28/2012 09:57 AM, Mark Zhang wrote:
On 12/28/2012 03:45 PM, Arto Merilainen wrote:
On 12/28/2012 08:47 AM, Mark Zhang wrote:
- /* Add fences */
- if (num_fences) {
tegra_stream_push(stream,
nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
host1x_uclass_wait_syncpt_r(), num_fences));
for (; num_fences; num_fences--, fence++) {
assert(tegra_fence_is_valid(fence));
This is useless. We already add "1 + num_fences" to num_words above. So move this "assert" before adding "1 + num_fences" to num_words makes sense.
The assertion checks the validity of a single fence - not if there is room in the command buffer.
The goal is to prevent having invalid fences in the command stream. If this check were not here it would be possible to initialise a fence with tegra_fence_clear() and put that fence into the stream.
My idea is, if one fence is invalid, then we should not count this in "num_words". In current code, if one fence is invalid, then this fence will not be pushed into the command stream, and the "num_words" shows a wrong command buffer size.
So I think we should:
- validate the fences, remove the invalid fence
- update num_words
- then you don't need to check fence here - I mean, before push a host1x
syncpt wait command into the active buffer of stream.
In my opinion asking tegra_stream_begin() to put a bad fence into the stream is a case we should never be. assert() kills the application immediately (in debug builds) and usually this helps the programmer for
- finding bugs 2) not doing bad code.
Yep, I agree. But in release builds, assert does nothing. So this checking doesn't make sense and also a wrong fence will be pushed into command buffer silently. And we always use release version in real products, so we can't count on this "assert".
"Silencing" is not a good solution especially in this case: tegra_stream_flush() returns an invalid fence when flushing fails. If the application chains submits (i.e. do a blit and then do another using the output of the first blit) it is crucial to be sure the first submit has been performed before starting the second one.
Yes. So I suggest doing fence checking at the beginning of the "tegra_stream_begin", if invalid fence found, return an error.
- Arto
On 12/28/2012 11:04 AM, Mark Zhang wrote:
On 12/28/2012 04:50 PM, Arto Merilainen wrote:
In my opinion asking tegra_stream_begin() to put a bad fence into the stream is a case we should never be. assert() kills the application immediately (in debug builds) and usually this helps the programmer for
- finding bugs 2) not doing bad code.
Yep, I agree. But in release builds, assert does nothing. So this checking doesn't make sense and also a wrong fence will be pushed into command buffer silently. And we always use release version in real products, so we can't count on this "assert".
The only pro of using assert is low (=no :-) ) overhead in release builds.
"Silencing" is not a good solution especially in this case: tegra_stream_flush() returns an invalid fence when flushing fails. If the application chains submits (i.e. do a blit and then do another using the output of the first blit) it is crucial to be sure the first submit has been performed before starting the second one.
Yes. So I suggest doing fence checking at the beginning of the "tegra_stream_begin", if invalid fence found, return an error.
This sounds reasonable.
- Arto
On Fri, Dec 28, 2012 at 09:45:48AM +0200, Arto Merilainen wrote:
On 12/28/2012 08:47 AM, Mark Zhang wrote:
+int tegra_fence_is_valid(const struct tegra_fence *fence) +{
- int valid = fence ? 1 : 0;
- valid = valid && fence->id != (uint32_t) -1;
- valid = valid && fence->id < 32;
Hardcode here. Assume always has 32 syncpts. Change to a micro wrapped with tegra version ifdef will be better.
You are correct. I will fix this.
I disagree. We shouldn't be hiding this kind of detail behind an #ifdef. Instead it should be detected at runtime. Otherwise you'll need to build different versions of libdrm for every generation of Tegra. That may be fine for NVIDIA provided BSPs, but distributions would have a very hard time dealing with that. What we want is software that works unmodified on as many generations of Tegra as possible.
Thierry
On 28.12.2012 22:48, Thierry Reding wrote:
I disagree. We shouldn't be hiding this kind of detail behind an #ifdef. Instead it should be detected at runtime. Otherwise you'll need to build different versions of libdrm for every generation of Tegra. That may be fine for NVIDIA provided BSPs, but distributions would have a very hard time dealing with that. What we want is software that works unmodified on as many generations of Tegra as possible.
I agree. The fences will be rejected by kernel and kernel knows about number of sync points in each host1x revision. So, we could just submit and look at return code.
Terje
On 12/31/2012 02:22 PM, Terje Bergström wrote:
On 28.12.2012 22:48, Thierry Reding wrote:
I disagree. We shouldn't be hiding this kind of detail behind an #ifdef. Instead it should be detected at runtime. Otherwise you'll need to build different versions of libdrm for every generation of Tegra. That may be fine for NVIDIA provided BSPs, but distributions would have a very hard time dealing with that. What we want is software that works unmodified on as many generations of Tegra as possible.
I agree. The fences will be rejected by kernel and kernel knows about number of sync points in each host1x revision. So, we could just submit and look at return code.
Agree. If we are able to do something dynamically, normally that'll be better.
Terje, we can get the Tegra version in FUSE. I think we don't need this kind of try-catch logics.
Mark
Terje
On 02.01.2013 04:44, Mark Zhang wrote:
Agree. If we are able to do something dynamically, normally that'll be better.
Terje, we can get the Tegra version in FUSE. I think we don't need this kind of try-catch logics.
We'd need to have in user space a map of SoC version -> number of sync points. As kernel already has this and checks for invalid fences, I don't think user space needs the same check.
We're anyway talking about a possibility of coding error, nothing that can happen on properly working software, so I wouldn't want to add any code that isn't absolutely necessary to catch that.
Terje
On 01/02/2013 02:31 PM, Terje Bergström wrote:
On 02.01.2013 04:44, Mark Zhang wrote:
Agree. If we are able to do something dynamically, normally that'll be better.
Terje, we can get the Tegra version in FUSE. I think we don't need this kind of try-catch logics.
We'd need to have in user space a map of SoC version -> number of sync points. As kernel already has this and checks for invalid fences, I don't think user space needs the same check.
We're anyway talking about a possibility of coding error, nothing that can happen on properly working software, so I wouldn't want to add any code that isn't absolutely necessary to catch that.
Ah, yes, my bad. It's libdrm, not host1x driver.
Mark
Terje
From: Francis Hart fhart@nvidia.com
This patch introduces a simple 2d library on top of stream library.
Signed-off-by: Francis Hart fhart@nvidia.com --- tegra/2d/hw_gr2d.h | 2614 ++++++++++++++++++++++++++++++++++++++++++ tegra/2d/tegra_2d_api.c | 235 ++++ tegra/2d/tegra_2d_color.c | 412 +++++++ tegra/2d/tegra_2d_color.h | 51 + tegra/2d/tegra_2d_context.c | 140 +++ tegra/2d/tegra_2d_context.h | 67 ++ tegra/2d/tegra_2d_copy.c | 209 ++++ tegra/2d/tegra_2d_copy.h | 38 + tegra/2d/tegra_2d_fill.c | 136 +++ tegra/2d/tegra_2d_fill.h | 36 + tegra/2d/tegra_2d_frcopy.c | 274 +++++ tegra/2d/tegra_2d_frcopy.h | 85 ++ tegra/2d/tegra_2d_g2copy.c | 272 +++++ tegra/2d/tegra_2d_g2copy.h | 88 ++ tegra/2d/tegra_2d_g2fill.c | 192 ++++ tegra/2d/tegra_2d_g2fill.h | 80 ++ tegra/2d/tegra_2d_reg_g2sb.h | 89 ++ tegra/2d/tegra_2d_reg_host.h | 119 ++ tegra/2d/tegra_2d_sbcopy.c | 388 +++++++ tegra/2d/tegra_2d_sbcopy.h | 94 ++ tegra/2d/tegra_2d_surface.c | 280 +++++ tegra/2d/tegra_2d_surface.h | 57 + tegra/2d/tegra_2d_util.c | 145 +++ tegra/2d/tegra_2d_util.h | 89 ++ tegra/Makefile.am | 13 +- tegra/tegra_2d.h | 223 ++++ 26 files changed, 6425 insertions(+), 1 deletion(-) create mode 100644 tegra/2d/hw_gr2d.h create mode 100644 tegra/2d/tegra_2d_api.c create mode 100644 tegra/2d/tegra_2d_color.c create mode 100644 tegra/2d/tegra_2d_color.h create mode 100644 tegra/2d/tegra_2d_context.c create mode 100644 tegra/2d/tegra_2d_context.h create mode 100644 tegra/2d/tegra_2d_copy.c create mode 100644 tegra/2d/tegra_2d_copy.h create mode 100644 tegra/2d/tegra_2d_fill.c create mode 100644 tegra/2d/tegra_2d_fill.h create mode 100644 tegra/2d/tegra_2d_frcopy.c create mode 100644 tegra/2d/tegra_2d_frcopy.h create mode 100644 tegra/2d/tegra_2d_g2copy.c create mode 100644 tegra/2d/tegra_2d_g2copy.h create mode 100644 tegra/2d/tegra_2d_g2fill.c create mode 100644 tegra/2d/tegra_2d_g2fill.h create mode 100644 tegra/2d/tegra_2d_reg_g2sb.h create mode 100644 tegra/2d/tegra_2d_reg_host.h create mode 100644 tegra/2d/tegra_2d_sbcopy.c create mode 100644 tegra/2d/tegra_2d_sbcopy.h create mode 100644 tegra/2d/tegra_2d_surface.c create mode 100644 tegra/2d/tegra_2d_surface.h create mode 100644 tegra/2d/tegra_2d_util.c create mode 100644 tegra/2d/tegra_2d_util.h create mode 100644 tegra/tegra_2d.h
diff --git a/tegra/2d/hw_gr2d.h b/tegra/2d/hw_gr2d.h new file mode 100644 index 0000000..4c48feb --- /dev/null +++ b/tegra/2d/hw_gr2d.h @@ -0,0 +1,2614 @@ +/* + * Copyright (C) 2012 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. + * + */ + + /* + * Function naming determines intended use: + * + * <x>_r(void) : Returns the offset for register <x>. + * + * <x>_w(void) : Returns the word offset for word (4 byte) element <x>. + * + * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits. + * + * <x>_<y>_f(uint32_t v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field <y> of register <x>. This value + * can be |'d with others to produce a full register value for + * register <x>. + * + * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This + * value can be ~'d and then &'d to clear the value of field <y> for + * register <x>. + * + * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted + * to place it at field <y> of register <x>. This value can be |'d + * with others to produce a full register value for <x>. + * + * <x>_<y>_v(uint32_t r) : Returns the value of field <y> from a full register + * <x> value 'r' after being shifted to place its LSB at bit 0. + * This value is suitable for direct comparison with other unshifted + * values appropriate for use in field <y> of register <x>. + * + * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for + * field <y> of register <x>. This value is suitable for direct + * comparison with unshifted values appropriate for use in field <y> + * of register <x>. + */ + +#ifndef __hw_gr2d_h__ +#define __hw_gr2d_h__ + +static inline uint32_t gr2d_trigger_r(void) +{ + return 0x9; +} +static inline uint32_t gr2d_trigger_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_trigger_trigger_s(void) +{ + return 16; +} +static inline uint32_t gr2d_trigger_trigger_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_trigger_trigger_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_trigger_trigger_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_cmdsel_r(void) +{ + return 0xc; +} +static inline uint32_t gr2d_cmdsel_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_cmdsel_sbor2d_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_sbor2d_f(uint32_t v) +{ + return (v & 0x1) << 0; +} +static inline uint32_t gr2d_cmdsel_sbor2d_m(void) +{ + return 0x1 << 0; +} +static inline uint32_t gr2d_cmdsel_sbor2d_v(uint32_t r) +{ + return (r >> 0) & 0x1; +} +static inline uint32_t gr2d_cmdsel_sbor2d_g2_v(void) +{ + return 0; +} +static inline uint32_t gr2d_cmdsel_sbor2d_sb_v(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_cbenable_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_cbenable_f(uint32_t v) +{ + return (v & 0x1) << 4; +} +static inline uint32_t gr2d_cmdsel_cbenable_m(void) +{ + return 0x1 << 4; +} +static inline uint32_t gr2d_cmdsel_cbenable_v(uint32_t r) +{ + return (r >> 4) & 0x1; +} +static inline uint32_t gr2d_cmdsel_cbenable_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_cmdsel_cbenable_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_vitrigger_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_vitrigger_f(uint32_t v) +{ + return (v & 0x1) << 5; +} +static inline uint32_t gr2d_cmdsel_vitrigger_m(void) +{ + return 0x1 << 5; +} +static inline uint32_t gr2d_cmdsel_vitrigger_v(uint32_t r) +{ + return (r >> 5) & 0x1; +} +static inline uint32_t gr2d_cmdsel_hosttrigger_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_hosttrigger_f(uint32_t v) +{ + return (v & 0x1) << 6; +} +static inline uint32_t gr2d_cmdsel_hosttrigger_m(void) +{ + return 0x1 << 6; +} +static inline uint32_t gr2d_cmdsel_hosttrigger_v(uint32_t r) +{ + return (r >> 6) & 0x1; +} +static inline uint32_t gr2d_cmdsel_cbsbdisable_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_cbsbdisable_f(uint32_t v) +{ + return (v & 0x1) << 7; +} +static inline uint32_t gr2d_cmdsel_cbsbdisable_m(void) +{ + return 0x1 << 7; +} +static inline uint32_t gr2d_cmdsel_cbsbdisable_v(uint32_t r) +{ + return (r >> 7) & 0x1; +} +static inline uint32_t gr2d_cmdsel_g2output_s(void) +{ + return 2; +} +static inline uint32_t gr2d_cmdsel_g2output_f(uint32_t v) +{ + return (v & 0x3) << 8; +} +static inline uint32_t gr2d_cmdsel_g2output_m(void) +{ + return 0x3 << 8; +} +static inline uint32_t gr2d_cmdsel_g2output_v(uint32_t r) +{ + return (r >> 8) & 0x3; +} +static inline uint32_t gr2d_cmdsel_g2output_memory_v(void) +{ + return 0; +} +static inline uint32_t gr2d_cmdsel_g2output_epp_v(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_g2output_reserved2_v(void) +{ + return 2; +} +static inline uint32_t gr2d_cmdsel_g2output_reserved3_v(void) +{ + return 3; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_f(uint32_t v) +{ + return (v & 0x1) << 10; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_m(void) +{ + return 0x1 << 10; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_v(uint32_t r) +{ + return (r >> 10) & 0x1; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_cmdsel_clip_source_top_bottom_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_frame_start_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_frame_start_f(uint32_t v) +{ + return (v & 0x1) << 14; +} +static inline uint32_t gr2d_cmdsel_frame_start_m(void) +{ + return 0x1 << 14; +} +static inline uint32_t gr2d_cmdsel_frame_start_v(uint32_t r) +{ + return (r >> 14) & 0x1; +} +static inline uint32_t gr2d_cmdsel_frame_end_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_frame_end_f(uint32_t v) +{ + return (v & 0x1) << 15; +} +static inline uint32_t gr2d_cmdsel_frame_end_m(void) +{ + return 0x1 << 15; +} +static inline uint32_t gr2d_cmdsel_frame_end_v(uint32_t r) +{ + return (r >> 15) & 0x1; +} +static inline uint32_t gr2d_cmdsel_buffer_index_s(void) +{ + return 8; +} +static inline uint32_t gr2d_cmdsel_buffer_index_f(uint32_t v) +{ + return (v & 0xff) << 16; +} +static inline uint32_t gr2d_cmdsel_buffer_index_m(void) +{ + return 0xff << 16; +} +static inline uint32_t gr2d_cmdsel_buffer_index_v(uint32_t r) +{ + return (r >> 16) & 0xff; +} +static inline uint32_t gr2d_cmdsel_linken_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_linken_f(uint32_t v) +{ + return (v & 0x1) << 24; +} +static inline uint32_t gr2d_cmdsel_linken_m(void) +{ + return 0x1 << 24; +} +static inline uint32_t gr2d_cmdsel_linken_v(uint32_t r) +{ + return (r >> 24) & 0x1; +} +static inline uint32_t gr2d_cmdsel_linkval_s(void) +{ + return 3; +} +static inline uint32_t gr2d_cmdsel_linkval_f(uint32_t v) +{ + return (v & 0x7) << 25; +} +static inline uint32_t gr2d_cmdsel_linkval_m(void) +{ + return 0x7 << 25; +} +static inline uint32_t gr2d_cmdsel_linkval_v(uint32_t r) +{ + return (r >> 25) & 0x7; +} +static inline uint32_t gr2d_cmdsel_priority_s(void) +{ + return 1; +} +static inline uint32_t gr2d_cmdsel_priority_f(uint32_t v) +{ + return (v & 0x1) << 28; +} +static inline uint32_t gr2d_cmdsel_priority_m(void) +{ + return 0x1 << 28; +} +static inline uint32_t gr2d_cmdsel_priority_v(uint32_t r) +{ + return (r >> 28) & 0x1; +} +static inline uint32_t gr2d_cmdsel_priority_low_v(void) +{ + return 0; +} +static inline uint32_t gr2d_cmdsel_priority_high_v(void) +{ + return 1; +} +static inline uint32_t gr2d_vdda_r(void) +{ + return 0x11; +} +static inline uint32_t gr2d_vdda_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_vdda_vdstep_s(void) +{ + return 32; +} +static inline uint32_t gr2d_vdda_vdstep_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_vdda_vdstep_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_vdda_vdstep_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_vddaini_r(void) +{ + return 0x12; +} +static inline uint32_t gr2d_vddaini_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_vddaini_vdtini_s(void) +{ + return 8; +} +static inline uint32_t gr2d_vddaini_vdtini_f(uint32_t v) +{ + return (v & 0xff) << 0; +} +static inline uint32_t gr2d_vddaini_vdtini_m(void) +{ + return 0xff << 0; +} +static inline uint32_t gr2d_vddaini_vdtini_v(uint32_t r) +{ + return (r >> 0) & 0xff; +} +static inline uint32_t gr2d_vddaini_vdbini_s(void) +{ + return 8; +} +static inline uint32_t gr2d_vddaini_vdbini_f(uint32_t v) +{ + return (v & 0xff) << 8; +} +static inline uint32_t gr2d_vddaini_vdbini_m(void) +{ + return 0xff << 8; +} +static inline uint32_t gr2d_vddaini_vdbini_v(uint32_t r) +{ + return (r >> 8) & 0xff; +} +static inline uint32_t gr2d_hdda_r(void) +{ + return 0x13; +} +static inline uint32_t gr2d_hdda_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_hdda_hdstep_s(void) +{ + return 32; +} +static inline uint32_t gr2d_hdda_hdstep_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_hdda_hdstep_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_hdda_hdstep_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_hddainils_r(void) +{ + return 0x14; +} +static inline uint32_t gr2d_hddainils_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_hddainils_hdini_s(void) +{ + return 8; +} +static inline uint32_t gr2d_hddainils_hdini_f(uint32_t v) +{ + return (v & 0xff) << 0; +} +static inline uint32_t gr2d_hddainils_hdini_m(void) +{ + return 0xff << 0; +} +static inline uint32_t gr2d_hddainils_hdini_v(uint32_t r) +{ + return (r >> 0) & 0xff; +} +static inline uint32_t gr2d_cscfirst_r(void) +{ + return 0x15; +} +static inline uint32_t gr2d_cscfirst_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_cscfirst_cub_s(void) +{ + return 10; +} +static inline uint32_t gr2d_cscfirst_cub_f(uint32_t v) +{ + return (v & 0x3ff) << 0; +} +static inline uint32_t gr2d_cscfirst_cub_m(void) +{ + return 0x3ff << 0; +} +static inline uint32_t gr2d_cscfirst_cub_v(uint32_t r) +{ + return (r >> 0) & 0x3ff; +} +static inline uint32_t gr2d_cscfirst_cvr_s(void) +{ + return 10; +} +static inline uint32_t gr2d_cscfirst_cvr_f(uint32_t v) +{ + return (v & 0x3ff) << 12; +} +static inline uint32_t gr2d_cscfirst_cvr_m(void) +{ + return 0x3ff << 12; +} +static inline uint32_t gr2d_cscfirst_cvr_v(uint32_t r) +{ + return (r >> 12) & 0x3ff; +} +static inline uint32_t gr2d_cscfirst_yos_s(void) +{ + return 8; +} +static inline uint32_t gr2d_cscfirst_yos_f(uint32_t v) +{ + return (v & 0xff) << 24; +} +static inline uint32_t gr2d_cscfirst_yos_m(void) +{ + return 0xff << 24; +} +static inline uint32_t gr2d_cscfirst_yos_v(uint32_t r) +{ + return (r >> 24) & 0xff; +} +static inline uint32_t gr2d_cscsecond_r(void) +{ + return 0x16; +} +static inline uint32_t gr2d_cscsecond_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_cscsecond_cug_s(void) +{ + return 9; +} +static inline uint32_t gr2d_cscsecond_cug_f(uint32_t v) +{ + return (v & 0x1ff) << 0; +} +static inline uint32_t gr2d_cscsecond_cug_m(void) +{ + return 0x1ff << 0; +} +static inline uint32_t gr2d_cscsecond_cug_v(uint32_t r) +{ + return (r >> 0) & 0x1ff; +} +static inline uint32_t gr2d_cscsecond_cur_s(void) +{ + return 10; +} +static inline uint32_t gr2d_cscsecond_cur_f(uint32_t v) +{ + return (v & 0x3ff) << 12; +} +static inline uint32_t gr2d_cscsecond_cur_m(void) +{ + return 0x3ff << 12; +} +static inline uint32_t gr2d_cscsecond_cur_v(uint32_t r) +{ + return (r >> 12) & 0x3ff; +} +static inline uint32_t gr2d_cscsecond_cyx_s(void) +{ + return 8; +} +static inline uint32_t gr2d_cscsecond_cyx_f(uint32_t v) +{ + return (v & 0xff) << 24; +} +static inline uint32_t gr2d_cscsecond_cyx_m(void) +{ + return 0xff << 24; +} +static inline uint32_t gr2d_cscsecond_cyx_v(uint32_t r) +{ + return (r >> 24) & 0xff; +} +static inline uint32_t gr2d_cscthird_r(void) +{ + return 0x17; +} +static inline uint32_t gr2d_cscthird_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_cscthird_cvg_s(void) +{ + return 9; +} +static inline uint32_t gr2d_cscthird_cvg_f(uint32_t v) +{ + return (v & 0x1ff) << 0; +} +static inline uint32_t gr2d_cscthird_cvg_m(void) +{ + return 0x1ff << 0; +} +static inline uint32_t gr2d_cscthird_cvg_v(uint32_t r) +{ + return (r >> 0) & 0x1ff; +} +static inline uint32_t gr2d_cscthird_cvb_s(void) +{ + return 10; +} +static inline uint32_t gr2d_cscthird_cvb_f(uint32_t v) +{ + return (v & 0x3ff) << 16; +} +static inline uint32_t gr2d_cscthird_cvb_m(void) +{ + return 0x3ff << 16; +} +static inline uint32_t gr2d_cscthird_cvb_v(uint32_t r) +{ + return (r >> 16) & 0x3ff; +} +static inline uint32_t gr2d_uba_r(void) +{ + return 0x1a; +} +static inline uint32_t gr2d_uba_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_uba_su1sa_s(void) +{ + return 32; +} +static inline uint32_t gr2d_uba_su1sa_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_uba_su1sa_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_uba_su1sa_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_vba_r(void) +{ + return 0x1b; +} +static inline uint32_t gr2d_vba_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_vba_sv1sa_s(void) +{ + return 32; +} +static inline uint32_t gr2d_vba_sv1sa_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_vba_sv1sa_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_vba_sv1sa_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_sbformat_r(void) +{ + return 0x1c; +} +static inline uint32_t gr2d_sbformat_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_sbformat_sifmt_s(void) +{ + return 5; +} +static inline uint32_t gr2d_sbformat_sifmt_f(uint32_t v) +{ + return (v & 0x1f) << 0; +} +static inline uint32_t gr2d_sbformat_sifmt_m(void) +{ + return 0x1f << 0; +} +static inline uint32_t gr2d_sbformat_sifmt_v(uint32_t r) +{ + return (r >> 0) & 0x1f; +} +static inline uint32_t gr2d_sbformat_sifmt_u8y8v8y8_ob_v(void) +{ + return 0; +} +static inline uint32_t gr2d_sbformat_sifmt_y8u8y8v8_ob_v(void) +{ + return 1; +} +static inline uint32_t gr2d_sbformat_sifmt_y8v8y8u8_ob_v(void) +{ + return 2; +} +static inline uint32_t gr2d_sbformat_sifmt_v8y8u8y8_ob_v(void) +{ + return 3; +} +static inline uint32_t gr2d_sbformat_sifmt_u8y8v8y8_tc_v(void) +{ + return 4; +} +static inline uint32_t gr2d_sbformat_sifmt_y8u8y8v8_tc_v(void) +{ + return 5; +} +static inline uint32_t gr2d_sbformat_sifmt_y8v8y8u8_tc_v(void) +{ + return 6; +} +static inline uint32_t gr2d_sbformat_sifmt_v8y8u8y8_tc_v(void) +{ + return 7; +} +static inline uint32_t gr2d_sbformat_sifmt_b5g6r5_v(void) +{ + return 8; +} +static inline uint32_t gr2d_sbformat_sifmt_b5g6r5bs_v(void) +{ + return 12; +} +static inline uint32_t gr2d_sbformat_sifmt_r8g8b8a8_v(void) +{ + return 14; +} +static inline uint32_t gr2d_sbformat_sifmt_b8g8r8a8_v(void) +{ + return 15; +} +static inline uint32_t gr2d_sbformat_difmt_s(void) +{ + return 5; +} +static inline uint32_t gr2d_sbformat_difmt_f(uint32_t v) +{ + return (v & 0x1f) << 8; +} +static inline uint32_t gr2d_sbformat_difmt_m(void) +{ + return 0x1f << 8; +} +static inline uint32_t gr2d_sbformat_difmt_v(uint32_t r) +{ + return (r >> 8) & 0x1f; +} +static inline uint32_t gr2d_sbformat_difmt_u8y8v8y8_ob_v(void) +{ + return 0; +} +static inline uint32_t gr2d_sbformat_difmt_y8u8y8v8_ob_v(void) +{ + return 1; +} +static inline uint32_t gr2d_sbformat_difmt_y8v8y8u8_ob_v(void) +{ + return 2; +} +static inline uint32_t gr2d_sbformat_difmt_v8y8u8y8_ob_v(void) +{ + return 3; +} +static inline uint32_t gr2d_sbformat_difmt_u8y8v8y8_tc_v(void) +{ + return 4; +} +static inline uint32_t gr2d_sbformat_difmt_y8u8y8v8_tc_v(void) +{ + return 5; +} +static inline uint32_t gr2d_sbformat_difmt_y8v8y8u8_tc_v(void) +{ + return 6; +} +static inline uint32_t gr2d_sbformat_difmt_v8y8u8y8_tc_v(void) +{ + return 7; +} +static inline uint32_t gr2d_sbformat_difmt_b5g6r5_v(void) +{ + return 8; +} +static inline uint32_t gr2d_sbformat_difmt_b5g6r5bs_v(void) +{ + return 12; +} +static inline uint32_t gr2d_sbformat_difmt_r8g8b8a8_v(void) +{ + return 14; +} +static inline uint32_t gr2d_sbformat_difmt_b8g8r8a8_v(void) +{ + return 15; +} +static inline uint32_t gr2d_controlsb_r(void) +{ + return 0x1d; +} +static inline uint32_t gr2d_controlsb_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_controlsb_imode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_imode_f(uint32_t v) +{ + return (v & 0x1) << 5; +} +static inline uint32_t gr2d_controlsb_imode_m(void) +{ + return 0x1 << 5; +} +static inline uint32_t gr2d_controlsb_imode_v(uint32_t r) +{ + return (r >> 5) & 0x1; +} +static inline uint32_t gr2d_controlsb_imode_multiplex_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_imode_planar_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_enavf_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_enavf_f(uint32_t v) +{ + return (v & 0x1) << 6; +} +static inline uint32_t gr2d_controlsb_enavf_m(void) +{ + return 0x1 << 6; +} +static inline uint32_t gr2d_controlsb_enavf_v(uint32_t r) +{ + return (r >> 6) & 0x1; +} +static inline uint32_t gr2d_controlsb_enavf_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_enavf_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_enahf_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_enahf_f(uint32_t v) +{ + return (v & 0x1) << 7; +} +static inline uint32_t gr2d_controlsb_enahf_m(void) +{ + return 0x1 << 7; +} +static inline uint32_t gr2d_controlsb_enahf_v(uint32_t r) +{ + return (r >> 7) & 0x1; +} +static inline uint32_t gr2d_controlsb_enahf_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_enahf_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_uvst_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsb_uvst_f(uint32_t v) +{ + return (v & 0x3) << 8; +} +static inline uint32_t gr2d_controlsb_uvst_m(void) +{ + return 0x3 << 8; +} +static inline uint32_t gr2d_controlsb_uvst_v(uint32_t r) +{ + return (r >> 8) & 0x3; +} +static inline uint32_t gr2d_controlsb_uvst_uvs2x_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_uvst_uvs1x_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_uvst_uvs4x_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsb_uvst_uvs_g2uvstride_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsb_vftype_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsb_vftype_f(uint32_t v) +{ + return (v & 0x3) << 16; +} +static inline uint32_t gr2d_controlsb_vftype_m(void) +{ + return 0x3 << 16; +} +static inline uint32_t gr2d_controlsb_vftype_v(uint32_t r) +{ + return (r >> 16) & 0x3; +} +static inline uint32_t gr2d_controlsb_vftype_interp_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_vftype_avg25_interp75_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_vftype_avg50_interp50_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsb_vftype_avg_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsb_vfen_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_vfen_f(uint32_t v) +{ + return (v & 0x1) << 18; +} +static inline uint32_t gr2d_controlsb_vfen_m(void) +{ + return 0x1 << 18; +} +static inline uint32_t gr2d_controlsb_vfen_v(uint32_t r) +{ + return (r >> 18) & 0x1; +} +static inline uint32_t gr2d_controlsb_vfen_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_vfen_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_discsc_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_discsc_f(uint32_t v) +{ + return (v & 0x1) << 19; +} +static inline uint32_t gr2d_controlsb_discsc_m(void) +{ + return 0x1 << 19; +} +static inline uint32_t gr2d_controlsb_discsc_v(uint32_t r) +{ + return (r >> 19) & 0x1; +} +static inline uint32_t gr2d_controlsb_discsc_enable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_discsc_disable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_hftype_s(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsb_hftype_f(uint32_t v) +{ + return (v & 0x7) << 20; +} +static inline uint32_t gr2d_controlsb_hftype_m(void) +{ + return 0x7 << 20; +} +static inline uint32_t gr2d_controlsb_hftype_v(uint32_t r) +{ + return (r >> 20) & 0x7; +} +static inline uint32_t gr2d_controlsb_hftype_interp_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_hftype_lpf1_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_hftype_lpf2_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsb_hftype_lpf3_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsb_hftype_lpf4_v(void) +{ + return 4; +} +static inline uint32_t gr2d_controlsb_hftype_lpf5_v(void) +{ + return 5; +} +static inline uint32_t gr2d_controlsb_hftype_lpf6_v(void) +{ + return 6; +} +static inline uint32_t gr2d_controlsb_hftype_disable_v(void) +{ + return 7; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_f(uint32_t v) +{ + return (v & 0x1) << 23; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_m(void) +{ + return 0x1 << 23; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_v(uint32_t r) +{ + return (r >> 23) & 0x1; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_rangeredfrm_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_sitype_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_sitype_f(uint32_t v) +{ + return (v & 0x1) << 24; +} +static inline uint32_t gr2d_controlsb_sitype_m(void) +{ + return 0x1 << 24; +} +static inline uint32_t gr2d_controlsb_sitype_v(uint32_t r) +{ + return (r >> 24) & 0x1; +} +static inline uint32_t gr2d_controlsb_sbsel_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_sbsel_f(uint32_t v) +{ + return (v & 0x1) << 25; +} +static inline uint32_t gr2d_controlsb_sbsel_m(void) +{ + return 0x1 << 25; +} +static inline uint32_t gr2d_controlsb_sbsel_v(uint32_t r) +{ + return (r >> 25) & 0x1; +} +static inline uint32_t gr2d_controlsb_sbsel_src_a_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_sbsel_src_b_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_dbsel_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_dbsel_f(uint32_t v) +{ + return (v & 0x1) << 26; +} +static inline uint32_t gr2d_controlsb_dbsel_m(void) +{ + return 0x1 << 26; +} +static inline uint32_t gr2d_controlsb_dbsel_v(uint32_t r) +{ + return (r >> 26) & 0x1; +} +static inline uint32_t gr2d_controlsb_dbsel_dst_a_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_dbsel_dst_b_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_keyen_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_keyen_f(uint32_t v) +{ + return (v & 0x1) << 27; +} +static inline uint32_t gr2d_controlsb_keyen_m(void) +{ + return 0x1 << 27; +} +static inline uint32_t gr2d_controlsb_keyen_v(uint32_t r) +{ + return (r >> 27) & 0x1; +} +static inline uint32_t gr2d_controlsb_keyen_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_keyen_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_kpol_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_kpol_f(uint32_t v) +{ + return (v & 0x1) << 28; +} +static inline uint32_t gr2d_controlsb_kpol_m(void) +{ + return 0x1 << 28; +} +static inline uint32_t gr2d_controlsb_kpol_v(uint32_t r) +{ + return (r >> 28) & 0x1; +} +static inline uint32_t gr2d_controlsb_kpol_within_bounds_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_kpol_outside_bounds_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_endith_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsb_endith_f(uint32_t v) +{ + return (v & 0x1) << 30; +} +static inline uint32_t gr2d_controlsb_endith_m(void) +{ + return 0x1 << 30; +} +static inline uint32_t gr2d_controlsb_endith_v(uint32_t r) +{ + return (r >> 30) & 0x1; +} +static inline uint32_t gr2d_controlsb_endith_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsb_endith_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_r(void) +{ + return 0x1e; +} +static inline uint32_t gr2d_controlsecond_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_controlsecond_bitswap_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_bitswap_f(uint32_t v) +{ + return (v & 0x1) << 1; +} +static inline uint32_t gr2d_controlsecond_bitswap_m(void) +{ + return 0x1 << 1; +} +static inline uint32_t gr2d_controlsecond_bitswap_v(uint32_t r) +{ + return (r >> 1) & 0x1; +} +static inline uint32_t gr2d_controlsecond_bitswap_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_bitswap_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_bebswap_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_bebswap_f(uint32_t v) +{ + return (v & 0x1) << 2; +} +static inline uint32_t gr2d_controlsecond_bebswap_m(void) +{ + return 0x1 << 2; +} +static inline uint32_t gr2d_controlsecond_bebswap_v(uint32_t r) +{ + return (r >> 2) & 0x1; +} +static inline uint32_t gr2d_controlsecond_bebswap_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_bebswap_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_bewswap_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_bewswap_f(uint32_t v) +{ + return (v & 0x1) << 3; +} +static inline uint32_t gr2d_controlsecond_bewswap_m(void) +{ + return 0x1 << 3; +} +static inline uint32_t gr2d_controlsecond_bewswap_v(uint32_t r) +{ + return (r >> 3) & 0x1; +} +static inline uint32_t gr2d_controlsecond_bewswap_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_bewswap_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_alptype_s(void) +{ + return 5; +} +static inline uint32_t gr2d_controlsecond_alptype_f(uint32_t v) +{ + return (v & 0x1f) << 4; +} +static inline uint32_t gr2d_controlsecond_alptype_m(void) +{ + return 0x1f << 4; +} +static inline uint32_t gr2d_controlsecond_alptype_v(uint32_t r) +{ + return (r >> 4) & 0x1f; +} +static inline uint32_t gr2d_controlsecond_alptype_fix_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_alptype_pl1bpp_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_alptype_pl2bpp_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsecond_alptype_pl4bpp_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsecond_alptype_pl8bpp_v(void) +{ + return 4; +} +static inline uint32_t gr2d_controlsecond_alptype_pl44bpp_v(void) +{ + return 5; +} +static inline uint32_t gr2d_controlsecond_alptype_pls1bpp_v(void) +{ + return 6; +} +static inline uint32_t gr2d_controlsecond_alptype_pls4bppal_v(void) +{ + return 7; +} +static inline uint32_t gr2d_controlsecond_alptype_pls4bpp_v(void) +{ + return 8; +} +static inline uint32_t gr2d_controlsecond_alptype_pls8bpp_v(void) +{ + return 9; +} +static inline uint32_t gr2d_controlsecond_alptype_pls8bx_v(void) +{ + return 10; +} +static inline uint32_t gr2d_controlsecond_alptype_pls1bppal_v(void) +{ + return 11; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_f(uint32_t v) +{ + return (v & 0x1) << 9; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_m(void) +{ + return 0x1 << 9; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_v(uint32_t r) +{ + return (r >> 9) & 0x1; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_alpsrcordst_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_clipc_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsecond_clipc_f(uint32_t v) +{ + return (v & 0x3) << 21; +} +static inline uint32_t gr2d_controlsecond_clipc_m(void) +{ + return 0x3 << 21; +} +static inline uint32_t gr2d_controlsecond_clipc_v(uint32_t r) +{ + return (r >> 21) & 0x3; +} +static inline uint32_t gr2d_controlsecond_fr_mode_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsecond_fr_mode_f(uint32_t v) +{ + return (v & 0x3) << 24; +} +static inline uint32_t gr2d_controlsecond_fr_mode_m(void) +{ + return 0x3 << 24; +} +static inline uint32_t gr2d_controlsecond_fr_mode_v(uint32_t r) +{ + return (r >> 24) & 0x3; +} +static inline uint32_t gr2d_controlsecond_fr_mode_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_fr_mode_src_dst_copy_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_fr_mode_square_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsecond_fr_mode_blank_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsecond_fr_type_s(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsecond_fr_type_f(uint32_t v) +{ + return (v & 0x7) << 26; +} +static inline uint32_t gr2d_controlsecond_fr_type_m(void) +{ + return 0x7 << 26; +} +static inline uint32_t gr2d_controlsecond_fr_type_v(uint32_t r) +{ + return (r >> 26) & 0x7; +} +static inline uint32_t gr2d_controlsecond_fr_type_flip_x_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_fr_type_flip_y_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_fr_type_trans_lr_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlsecond_fr_type_trans_rl_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlsecond_fr_type_rot_90_v(void) +{ + return 4; +} +static inline uint32_t gr2d_controlsecond_fr_type_rot_180_v(void) +{ + return 5; +} +static inline uint32_t gr2d_controlsecond_fr_type_rot_270_v(void) +{ + return 6; +} +static inline uint32_t gr2d_controlsecond_fr_type_identity_v(void) +{ + return 7; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_f(uint32_t v) +{ + return (v & 0x1) << 29; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_m(void) +{ + return 0x1 << 29; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_v(uint32_t r) +{ + return (r >> 29) & 0x1; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlsecond_fr_readwait_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_r(void) +{ + return 0x1f; +} +static inline uint32_t gr2d_controlmain_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_controlmain_cmdt_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_cmdt_f(uint32_t v) +{ + return (v & 0x3) << 0; +} +static inline uint32_t gr2d_controlmain_cmdt_m(void) +{ + return 0x3 << 0; +} +static inline uint32_t gr2d_controlmain_cmdt_v(uint32_t r) +{ + return (r >> 0) & 0x3; +} +static inline uint32_t gr2d_controlmain_cmdt_bitblt_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_cmdt_linedraw_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_cmdt_vcaa_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_cmdt_reserved1_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlmain_turbofill_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_turbofill_f(uint32_t v) +{ + return (v & 0x1) << 2; +} +static inline uint32_t gr2d_controlmain_turbofill_m(void) +{ + return 0x1 << 2; +} +static inline uint32_t gr2d_controlmain_turbofill_v(uint32_t r) +{ + return (r >> 2) & 0x1; +} +static inline uint32_t gr2d_controlmain_test0bit_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_test0bit_f(uint32_t v) +{ + return (v & 0x1) << 3; +} +static inline uint32_t gr2d_controlmain_test0bit_m(void) +{ + return 0x1 << 3; +} +static inline uint32_t gr2d_controlmain_test0bit_v(uint32_t r) +{ + return (r >> 3) & 0x1; +} +static inline uint32_t gr2d_controlmain_test0bit_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_test0bit_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_faden_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_faden_f(uint32_t v) +{ + return (v & 0x1) << 4; +} +static inline uint32_t gr2d_controlmain_faden_m(void) +{ + return 0x1 << 4; +} +static inline uint32_t gr2d_controlmain_faden_v(uint32_t r) +{ + return (r >> 4) & 0x1; +} +static inline uint32_t gr2d_controlmain_faden_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_faden_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_alpen_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_alpen_f(uint32_t v) +{ + return (v & 0x1) << 5; +} +static inline uint32_t gr2d_controlmain_alpen_m(void) +{ + return 0x1 << 5; +} +static inline uint32_t gr2d_controlmain_alpen_v(uint32_t r) +{ + return (r >> 5) & 0x1; +} +static inline uint32_t gr2d_controlmain_srcsld_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcsld_f(uint32_t v) +{ + return (v & 0x1) << 6; +} +static inline uint32_t gr2d_controlmain_srcsld_m(void) +{ + return 0x1 << 6; +} +static inline uint32_t gr2d_controlmain_srcsld_v(uint32_t r) +{ + return (r >> 6) & 0x1; +} +static inline uint32_t gr2d_controlmain_srcsld_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_srcsld_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patsld_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patsld_f(uint32_t v) +{ + return (v & 0x1) << 7; +} +static inline uint32_t gr2d_controlmain_patsld_m(void) +{ + return 0x1 << 7; +} +static inline uint32_t gr2d_controlmain_patsld_v(uint32_t r) +{ + return (r >> 7) & 0x1; +} +static inline uint32_t gr2d_controlmain_patsld_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_patsld_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patfl_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patfl_f(uint32_t v) +{ + return (v & 0x1) << 8; +} +static inline uint32_t gr2d_controlmain_patfl_m(void) +{ + return 0x1 << 8; +} +static inline uint32_t gr2d_controlmain_patfl_v(uint32_t r) +{ + return (r >> 8) & 0x1; +} +static inline uint32_t gr2d_controlmain_patfl_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_patfl_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_xdir_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_xdir_f(uint32_t v) +{ + return (v & 0x1) << 9; +} +static inline uint32_t gr2d_controlmain_xdir_m(void) +{ + return 0x1 << 9; +} +static inline uint32_t gr2d_controlmain_xdir_v(uint32_t r) +{ + return (r >> 9) & 0x1; +} +static inline uint32_t gr2d_controlmain_ydir_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_ydir_f(uint32_t v) +{ + return (v & 0x1) << 10; +} +static inline uint32_t gr2d_controlmain_ydir_m(void) +{ + return 0x1 << 10; +} +static inline uint32_t gr2d_controlmain_ydir_v(uint32_t r) +{ + return (r >> 10) & 0x1; +} +static inline uint32_t gr2d_controlmain_xytdw_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_xytdw_f(uint32_t v) +{ + return (v & 0x1) << 11; +} +static inline uint32_t gr2d_controlmain_xytdw_m(void) +{ + return 0x1 << 11; +} +static inline uint32_t gr2d_controlmain_xytdw_v(uint32_t r) +{ + return (r >> 11) & 0x1; +} +static inline uint32_t gr2d_controlmain_srcpack_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcpack_f(uint32_t v) +{ + return (v & 0x1) << 12; +} +static inline uint32_t gr2d_controlmain_srcpack_m(void) +{ + return 0x1 << 12; +} +static inline uint32_t gr2d_controlmain_srcpack_v(uint32_t r) +{ + return (r >> 12) & 0x1; +} +static inline uint32_t gr2d_controlmain_srcpack_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_srcpack_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patpack_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patpack_f(uint32_t v) +{ + return (v & 0x1) << 13; +} +static inline uint32_t gr2d_controlmain_patpack_m(void) +{ + return 0x1 << 13; +} +static inline uint32_t gr2d_controlmain_patpack_v(uint32_t r) +{ + return (r >> 13) & 0x1; +} +static inline uint32_t gr2d_controlmain_patpack_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_patpack_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_yflip_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_yflip_f(uint32_t v) +{ + return (v & 0x1) << 14; +} +static inline uint32_t gr2d_controlmain_yflip_m(void) +{ + return 0x1 << 14; +} +static inline uint32_t gr2d_controlmain_yflip_v(uint32_t r) +{ + return (r >> 14) & 0x1; +} +static inline uint32_t gr2d_controlmain_yflip_dsiable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_yflip_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcsel_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcsel_f(uint32_t v) +{ + return (v & 0x1) << 15; +} +static inline uint32_t gr2d_controlmain_srcsel_m(void) +{ + return 0x1 << 15; +} +static inline uint32_t gr2d_controlmain_srcsel_v(uint32_t r) +{ + return (r >> 15) & 0x1; +} +static inline uint32_t gr2d_controlmain_srcsel_screen_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_srcsel_memory_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_dstcd_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_dstcd_f(uint32_t v) +{ + return (v & 0x3) << 16; +} +static inline uint32_t gr2d_controlmain_dstcd_m(void) +{ + return 0x3 << 16; +} +static inline uint32_t gr2d_controlmain_dstcd_v(uint32_t r) +{ + return (r >> 16) & 0x3; +} +static inline uint32_t gr2d_controlmain_dstcd_bpp8_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_dstcd_bpp16_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_dstcd_bpp32_v(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_dstcd_reserved3_v(void) +{ + return 3; +} +static inline uint32_t gr2d_controlmain_dstt_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_dstt_f(uint32_t v) +{ + return (v & 0x3) << 18; +} +static inline uint32_t gr2d_controlmain_dstt_m(void) +{ + return 0x3 << 18; +} +static inline uint32_t gr2d_controlmain_dstt_v(uint32_t r) +{ + return (r >> 18) & 0x3; +} +static inline uint32_t gr2d_controlmain_srccd_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srccd_f(uint32_t v) +{ + return (v & 0x1) << 20; +} +static inline uint32_t gr2d_controlmain_srccd_m(void) +{ + return 0x1 << 20; +} +static inline uint32_t gr2d_controlmain_srccd_v(uint32_t r) +{ + return (r >> 20) & 0x1; +} +static inline uint32_t gr2d_controlmain_hlmono_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_hlmono_f(uint32_t v) +{ + return (v & 0x1) << 21; +} +static inline uint32_t gr2d_controlmain_hlmono_m(void) +{ + return 0x1 << 21; +} +static inline uint32_t gr2d_controlmain_hlmono_v(uint32_t r) +{ + return (r >> 21) & 0x1; +} +static inline uint32_t gr2d_controlmain_srct_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_srct_f(uint32_t v) +{ + return (v & 0x3) << 22; +} +static inline uint32_t gr2d_controlmain_srct_m(void) +{ + return 0x3 << 22; +} +static inline uint32_t gr2d_controlmain_srct_v(uint32_t r) +{ + return (r >> 22) & 0x3; +} +static inline uint32_t gr2d_controlmain_srcbas_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcbas_f(uint32_t v) +{ + return (v & 0x1) << 24; +} +static inline uint32_t gr2d_controlmain_srcbas_m(void) +{ + return 0x1 << 24; +} +static inline uint32_t gr2d_controlmain_srcbas_v(uint32_t r) +{ + return (r >> 24) & 0x1; +} +static inline uint32_t gr2d_controlmain_gcsw_s(void) +{ + return 2; +} +static inline uint32_t gr2d_controlmain_gcsw_f(uint32_t v) +{ + return (v & 0x3) << 25; +} +static inline uint32_t gr2d_controlmain_gcsw_m(void) +{ + return 0x3 << 25; +} +static inline uint32_t gr2d_controlmain_gcsw_v(uint32_t r) +{ + return (r >> 25) & 0x3; +} +static inline uint32_t gr2d_controlmain_srcdir_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcdir_f(uint32_t v) +{ + return (v & 0x1) << 27; +} +static inline uint32_t gr2d_controlmain_srcdir_m(void) +{ + return 0x1 << 27; +} +static inline uint32_t gr2d_controlmain_srcdir_v(uint32_t r) +{ + return (r >> 27) & 0x1; +} +static inline uint32_t gr2d_controlmain_dstdir_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_dstdir_f(uint32_t v) +{ + return (v & 0x1) << 28; +} +static inline uint32_t gr2d_controlmain_dstdir_m(void) +{ + return 0x1 << 28; +} +static inline uint32_t gr2d_controlmain_dstdir_v(uint32_t r) +{ + return (r >> 28) & 0x1; +} +static inline uint32_t gr2d_controlmain_patsel_s(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_patsel_f(uint32_t v) +{ + return (v & 0x1) << 30; +} +static inline uint32_t gr2d_controlmain_patsel_m(void) +{ + return 0x1 << 30; +} +static inline uint32_t gr2d_controlmain_patsel_v(uint32_t r) +{ + return (r >> 30) & 0x1; +} +static inline uint32_t gr2d_controlmain_patsel_screen_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_patsel_memory_v(void) +{ + return 1; +} +static inline uint32_t gr2d_ropfade_r(void) +{ + return 0x20; +} +static inline uint32_t gr2d_ropfade_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_ropfade_rop_s(void) +{ + return 8; +} +static inline uint32_t gr2d_ropfade_rop_f(uint32_t v) +{ + return (v & 0xff) << 0; +} +static inline uint32_t gr2d_ropfade_rop_m(void) +{ + return 0xff << 0; +} +static inline uint32_t gr2d_ropfade_rop_v(uint32_t r) +{ + return (r >> 0) & 0xff; +} +static inline uint32_t gr2d_ropfade_fadcoe_s(void) +{ + return 8; +} +static inline uint32_t gr2d_ropfade_fadcoe_f(uint32_t v) +{ + return (v & 0xff) << 16; +} +static inline uint32_t gr2d_ropfade_fadcoe_m(void) +{ + return 0xff << 16; +} +static inline uint32_t gr2d_ropfade_fadcoe_v(uint32_t r) +{ + return (r >> 16) & 0xff; +} +static inline uint32_t gr2d_ropfade_fadoff_s(void) +{ + return 8; +} +static inline uint32_t gr2d_ropfade_fadoff_f(uint32_t v) +{ + return (v & 0xff) << 24; +} +static inline uint32_t gr2d_ropfade_fadoff_m(void) +{ + return 0xff << 24; +} +static inline uint32_t gr2d_ropfade_fadoff_v(uint32_t r) +{ + return (r >> 24) & 0xff; +} +static inline uint32_t gr2d_dstba_r(void) +{ + return 0x2b; +} +static inline uint32_t gr2d_dstba_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_dstba_dstba_s(void) +{ + return 32; +} +static inline uint32_t gr2d_dstba_dstba_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_dstba_dstba_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_dstba_dstba_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_dstst_r(void) +{ + return 0x2e; +} +static inline uint32_t gr2d_dstst_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_dstst_dsts_s(void) +{ + return 16; +} +static inline uint32_t gr2d_dstst_dsts_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_dstst_dsts_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_dstst_dsts_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_srcba_r(void) +{ + return 0x31; +} +static inline uint32_t gr2d_srcba_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcba_srcba_s(void) +{ + return 32; +} +static inline uint32_t gr2d_srcba_srcba_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_srcba_srcba_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_srcba_srcba_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_srcst_r(void) +{ + return 0x33; +} +static inline uint32_t gr2d_srcst_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcst_srcs_s(void) +{ + return 16; +} +static inline uint32_t gr2d_srcst_srcs_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_srcst_srcs_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_srcst_srcs_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_srcfgc_r(void) +{ + return 0x35; +} +static inline uint32_t gr2d_srcfgc_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcfgc_srcfgc_s(void) +{ + return 32; +} +static inline uint32_t gr2d_srcfgc_srcfgc_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_srcfgc_srcfgc_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_srcfgc_srcfgc_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_srcsize_r(void) +{ + return 0x37; +} +static inline uint32_t gr2d_srcsize_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcsize_srcwidth_s(void) +{ + return 15; +} +static inline uint32_t gr2d_srcsize_srcwidth_f(uint32_t v) +{ + return (v & 0x7fff) << 0; +} +static inline uint32_t gr2d_srcsize_srcwidth_m(void) +{ + return 0x7fff << 0; +} +static inline uint32_t gr2d_srcsize_srcwidth_v(uint32_t r) +{ + return (r >> 0) & 0x7fff; +} +static inline uint32_t gr2d_srcsize_srcheight_s(void) +{ + return 15; +} +static inline uint32_t gr2d_srcsize_srcheight_f(uint32_t v) +{ + return (v & 0x7fff) << 16; +} +static inline uint32_t gr2d_srcsize_srcheight_m(void) +{ + return 0x7fff << 16; +} +static inline uint32_t gr2d_srcsize_srcheight_v(uint32_t r) +{ + return (r >> 16) & 0x7fff; +} +static inline uint32_t gr2d_dstsize_r(void) +{ + return 0x38; +} +static inline uint32_t gr2d_dstsize_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_dstsize_dstwidth_s(void) +{ + return 15; +} +static inline uint32_t gr2d_dstsize_dstwidth_f(uint32_t v) +{ + return (v & 0x7fff) << 0; +} +static inline uint32_t gr2d_dstsize_dstwidth_m(void) +{ + return 0x7fff << 0; +} +static inline uint32_t gr2d_dstsize_dstwidth_v(uint32_t r) +{ + return (r >> 0) & 0x7fff; +} +static inline uint32_t gr2d_dstsize_dstheight_s(void) +{ + return 15; +} +static inline uint32_t gr2d_dstsize_dstheight_f(uint32_t v) +{ + return (v & 0x7fff) << 16; +} +static inline uint32_t gr2d_dstsize_dstheight_m(void) +{ + return 0x7fff << 16; +} +static inline uint32_t gr2d_dstsize_dstheight_v(uint32_t r) +{ + return (r >> 16) & 0x7fff; +} +static inline uint32_t gr2d_srcps_r(void) +{ + return 0x39; +} +static inline uint32_t gr2d_srcps_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcps_srcx_s(void) +{ + return 16; +} +static inline uint32_t gr2d_srcps_srcx_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_srcps_srcx_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_srcps_srcx_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_srcps_srcy_s(void) +{ + return 16; +} +static inline uint32_t gr2d_srcps_srcy_f(uint32_t v) +{ + return (v & 0xffff) << 16; +} +static inline uint32_t gr2d_srcps_srcy_m(void) +{ + return 0xffff << 16; +} +static inline uint32_t gr2d_srcps_srcy_v(uint32_t r) +{ + return (r >> 16) & 0xffff; +} +static inline uint32_t gr2d_dstps_r(void) +{ + return 0x3a; +} +static inline uint32_t gr2d_dstps_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_dstps_dstx_s(void) +{ + return 16; +} +static inline uint32_t gr2d_dstps_dstx_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_dstps_dstx_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_dstps_dstx_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_dstps_dsty_s(void) +{ + return 16; +} +static inline uint32_t gr2d_dstps_dsty_f(uint32_t v) +{ + return (v & 0xffff) << 16; +} +static inline uint32_t gr2d_dstps_dsty_m(void) +{ + return 0xffff << 16; +} +static inline uint32_t gr2d_dstps_dsty_v(uint32_t r) +{ + return (r >> 16) & 0xffff; +} +static inline uint32_t gr2d_uvstride_r(void) +{ + return 0x44; +} +static inline uint32_t gr2d_uvstride_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_uvstride_uvstride_s(void) +{ + return 16; +} +static inline uint32_t gr2d_uvstride_uvstride_f(uint32_t v) +{ + return (v & 0xffff) << 0; +} +static inline uint32_t gr2d_uvstride_uvstride_m(void) +{ + return 0xffff << 0; +} +static inline uint32_t gr2d_uvstride_uvstride_v(uint32_t r) +{ + return (r >> 0) & 0xffff; +} +static inline uint32_t gr2d_tilemode_r(void) +{ + return 0x46; +} +static inline uint32_t gr2d_tilemode_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 0; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_m(void) +{ + return 0x1 << 0; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_v(uint32_t r) +{ + return (r >> 0) & 0x1; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_src_y_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 4; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_m(void) +{ + return 0x1 << 4; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_v(uint32_t r) +{ + return (r >> 4) & 0x1; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_src_uv_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 8; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_m(void) +{ + return 0x1 << 8; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_v(uint32_t r) +{ + return (r >> 8) & 0x1; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_pat_y_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 12; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_m(void) +{ + return 0x1 << 12; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_v(uint32_t r) +{ + return (r >> 12) & 0x1; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_pat_uv_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 16; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_m(void) +{ + return 0x1 << 16; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_v(uint32_t r) +{ + return (r >> 16) & 0x1; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_dst_rd_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_s(void) +{ + return 1; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_f(uint32_t v) +{ + return (v & 0x1) << 20; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_m(void) +{ + return 0x1 << 20; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_v(uint32_t r) +{ + return (r >> 20) & 0x1; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_linear_v(void) +{ + return 0; +} +static inline uint32_t gr2d_tilemode_dst_wr_tile_mode_tiled_v(void) +{ + return 1; +} +static inline uint32_t gr2d_srcba_sb_surfbase_r(void) +{ + return 0x48; +} +static inline uint32_t gr2d_srcba_sb_surfbase_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_srcba_sb_surfbase_src_addr_s(void) +{ + return 32; +} +static inline uint32_t gr2d_srcba_sb_surfbase_src_addr_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_srcba_sb_surfbase_src_addr_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_srcba_sb_surfbase_src_addr_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_dstba_sb_surfbase_r(void) +{ + return 0x49; +} +static inline uint32_t gr2d_dstba_sb_surfbase_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_dstba_sb_surfbase_dst_addr_s(void) +{ + return 32; +} +static inline uint32_t gr2d_dstba_sb_surfbase_dst_addr_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_dstba_sb_surfbase_dst_addr_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_dstba_sb_surfbase_dst_addr_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_vba_sb_surfbase_r(void) +{ + return 0x4b; +} +static inline uint32_t gr2d_vba_sb_surfbase_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_vba_sb_surfbase_v_addr_s(void) +{ + return 32; +} +static inline uint32_t gr2d_vba_sb_surfbase_v_addr_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_vba_sb_surfbase_v_addr_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_vba_sb_surfbase_v_addr_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} +static inline uint32_t gr2d_uba_sb_surfbase_r(void) +{ + return 0x4c; +} +static inline uint32_t gr2d_uba_sb_surfbase_reset_val_v(void) +{ + return 0x0; +} +static inline uint32_t gr2d_uba_sb_surfbase_u_addr_s(void) +{ + return 32; +} +static inline uint32_t gr2d_uba_sb_surfbase_u_addr_f(uint32_t v) +{ + return (v & 0xffffffff) << 0; +} +static inline uint32_t gr2d_uba_sb_surfbase_u_addr_m(void) +{ + return 0xffffffff << 0; +} +static inline uint32_t gr2d_uba_sb_surfbase_u_addr_v(uint32_t r) +{ + return (r >> 0) & 0xffffffff; +} + +#endif /* __hw_gr2d_h__ */ diff --git a/tegra/2d/tegra_2d_api.c b/tegra/2d/tegra_2d_api.c new file mode 100644 index 0000000..a4b5101 --- /dev/null +++ b/tegra/2d/tegra_2d_api.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include "tegra_2d.h" +#include "tegra_2d_context.h" +#include "tegra_2d_copy.h" +#include "tegra_2d_fill.h" +#include "tegra_2d_color.h" +#include "tegra_2d_surface.h" +#include "tegra_2d_util.h" + +#define ENTER() \ + if (ctx->log_enable) LOG("> %s\n", __func__) + +#define RETURN(x) \ + if (ctx->log_enable) \ + LOG("- %s: %s\n", __func__, result_to_str((enum tegra_2d_result) x)); \ + return x + +#define RETURN_VOID() \ + if (ctx->log_enable) \ + LOG("- %s\n", __func__); \ + return + +struct tegra_2d_context * +tegra_2d_open(int fd) +{ + struct tegra_2d_ictx *ictx; + + ictx = open2d(fd); + + return (struct tegra_2d_context *) ictx; +} + +void +tegra_2d_close(struct tegra_2d_context *ctx) +{ + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return; + + ENTER(); + + close2d(ictx); +} + +int +tegra_2d_begin(struct tegra_2d_context *ctx, + const struct tegra_fence *fence) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = begin2d(ictx, fence); + + RETURN(result); +} + +int +tegra_2d_end(struct tegra_2d_context *ctx, + struct tegra_fence *fence) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = end2d(ictx, fence); + + RETURN(result); +} + +int +tegra_2d_fill(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface_color *color, + const struct tegra_2d_rect *dst_rect) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = fill2d(ictx, dst, color, dst_rect); + + RETURN(result); +} + +int +tegra_2d_copy(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface *src, + const struct tegra_2d_rect *dst_rect, + const struct tegra_2d_rect *src_rect, + enum tegra_2d_transform transform) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = copy2d(ictx, dst, src, dst_rect, src_rect, transform); + + RETURN(result); +} + +int +tegra_2d_compute_requirements(const struct tegra_2d_plane *plane, + uint32_t *num_bytes, + uint32_t *alignment, + uint32_t *pitch) +{ + int result; + + result = compute_requirements(plane, num_bytes, alignment, pitch); + + return result; +} + +int +tegra_2d_allocate_surface(struct tegra_2d_context *ctx, + struct tegra_2d_surface *surface) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = allocate_surface(ictx, surface); + + RETURN(result); +} + +void +tegra_2d_free_surface(struct tegra_2d_context *ctx, + struct tegra_2d_surface *surface) +{ + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return; + + ENTER(); + + free_surface(ictx, surface); + + RETURN_VOID(); +} + +int +tegra_2d_dump_surface(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *surface, + const char *filename) +{ + int result; + struct tegra_2d_ictx *ictx = (struct tegra_2d_ictx *) ctx; + + if (ctx == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + ENTER(); + + result = dump_surface(ictx, surface, filename); + + RETURN(result); +} + +void +tegra_2d_color_convert(struct tegra_2d_surface_color *dst, + const struct tegra_2d_surface_color *src) +{ + color_convert(dst, src); +} + +void +tegra_2d_color_to_rgba(const struct tegra_2d_surface_color *src, + uint32_t *r, + uint32_t *g, + uint32_t *b, + uint32_t *a) +{ + color_to_rgba(src, r, g, b, a); +} + +void +tegra_2d_color_from_rgba(struct tegra_2d_surface_color *dst, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a) +{ + color_from_rgba(dst, r, g, b, a); +} diff --git a/tegra/2d/tegra_2d_color.c b/tegra/2d/tegra_2d_color.c new file mode 100644 index 0000000..089c5c2 --- /dev/null +++ b/tegra/2d/tegra_2d_color.c @@ -0,0 +1,412 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include "tegra_2d.h" +#include "tegra_2d_color.h" +#include "tegra_2d_util.h" + +void +color_convert(struct tegra_2d_surface_color *dst, + const struct tegra_2d_surface_color *src) +{ + int i; + uint32_t r, g, b, a; + + ASSERT(dst); + ASSERT(src); + + if (src->num_planes != dst->num_planes) + goto convert; + + for (i=0; i<src->num_planes; ++i) + { + if (src->planes[i].format != dst->planes[i].format) + goto convert; + + dst->planes[i].value = src->planes[i].value; + } + + return; + +convert: + color_to_rgba(src, &r, &g, &b, &a); + color_from_rgba(dst, r, g, b, a); +} + +static void +rgb_to_yuv(uint32_t *y, uint32_t *u, uint32_t *v, + uint32_t r, uint32_t g, uint32_t b) +{ + int32_t yt, ut, vt; + yt = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16; + ut = ((-38 * (int32_t)r - 74 * (int32_t)g + 112 * (int32_t)b + 128) >> 8) + 128; + vt = ((112 * (int32_t)r - 94 * (int32_t)g - 18 * (int32_t)b + 128) >> 8) + 128; + *y = CLAMP(yt, 0, 255); + *u = CLAMP(ut, 0, 255); + *v = CLAMP(vt, 0, 255); +} + +static void +yuv_to_rgb(uint32_t *r, uint32_t *g, uint32_t *b, + uint32_t y, uint32_t u, uint32_t v) +{ + int32_t c = y - 16; + int32_t d = u - 128; + int32_t e = v - 128; + *r = CLAMP((298*c + 409*e + 128) >> 8, 0, 255); + *g = CLAMP(((298*c - 100*d - 208*e + 128) >> 8), 0, 255); + *b = CLAMP(((298*c + 516*d + 128) >> 8), 0, 255); +} + +static void +get_components(const struct tegra_2d_surface_color *src, + uint32_t *x, + uint32_t *y, + uint32_t *z, + uint32_t *w) +{ + int i; + + for (i=0; i<src->num_planes; ++i) + { + uint32_t value = src->planes[i].value; + + switch (src->planes[i].format) + { + case TEGRA_2D_FORMAT_A8R8G8B8: + *w = (value >> 24) & 0xff; + *x = (value >> 16) & 0xff; + *y = (value >> 8) & 0xff; + *z = (value >> 0) & 0xff; + break; + + case TEGRA_2D_FORMAT_A8B8G8R8: + *w = (value >> 24) & 0xff; + *z = (value >> 16) & 0xff; + *y = (value >> 8) & 0xff; + *x = (value >> 0) & 0xff; + break; + + case TEGRA_2D_FORMAT_R8G8B8A8: + *x = (value >> 24) & 0xff; + *y = (value >> 16) & 0xff; + *z = (value >> 8) & 0xff; + *w = (value >> 0) & 0xff; + break; + + case TEGRA_2D_FORMAT_B8G8R8A8: + *z = (value >> 24) & 0xff; + *y = (value >> 16) & 0xff; + *x = (value >> 8) & 0xff; + *w = (value >> 0) & 0xff; + break; + + case TEGRA_2D_FORMAT_A4R4G4B4: + *w = ((value >> 12) & 0x0f) << 4; + *x = ((value >> 8) & 0x0f) << 4; + *y = ((value >> 4) & 0x0f) << 4; + *z = ((value >> 0) & 0x0f) << 4; + break; + + case TEGRA_2D_FORMAT_R4G4B4A4: + *x = ((value >> 12) & 0x0f) << 4; + *y = ((value >> 8) & 0x0f) << 4; + *z = ((value >> 4) & 0x0f) << 4; + *w = ((value >> 0) & 0x0f) << 4; + break; + + case TEGRA_2D_FORMAT_R5G6B5: + *x = ((value >> 11) & 0x1f) << 3; + *y = ((value >> 5) & 0x3f) << 2; + *z = ((value >> 0) & 0x1f) << 3; + break; + + case TEGRA_2D_FORMAT_A1R5G5B5: + *w = ((value >> 11) & 0x1f) << 3; + *x = ((value >> 6) & 0x1f) << 3; + *y = ((value >> 1) & 0x1f) << 3; + *z = ((value >> 0) & 0x01) << 7; + break; + + case TEGRA_2D_FORMAT_Y8: + *x = value & 0xff; + break; + + case TEGRA_2D_FORMAT_U8: + *y = value & 0xff; + break; + + case TEGRA_2D_FORMAT_V8: + *z = value & 0xff; + break; + + case TEGRA_2D_FORMAT_U8_V8: + *y = ((uint8_t *) &value)[0]; + *z = ((uint8_t *) &value)[1]; + break; + + case TEGRA_2D_FORMAT_V8_U8: + *z = ((uint8_t *) &value)[0]; + *y = ((uint8_t *) &value)[1]; + break; + + case TEGRA_2D_FORMAT_UYVY: + *y = ((uint8_t *) &value)[0]; + *x = ((uint8_t *) &value)[1]; + *z = ((uint8_t *) &value)[2]; + break; + + case TEGRA_2D_FORMAT_VYUY: + *z = ((uint8_t *) &value)[0]; + *x = ((uint8_t *) &value)[1]; + *y = ((uint8_t *) &value)[2]; + break; + + case TEGRA_2D_FORMAT_YUYV: + *x = ((uint8_t *) &value)[0]; + *y = ((uint8_t *) &value)[1]; + *z = ((uint8_t *) &value)[3]; + break; + + case TEGRA_2D_FORMAT_YVYU: + *x = ((uint8_t *) &value)[0]; + *z = ((uint8_t *) &value)[1]; + *y = ((uint8_t *) &value)[3]; + break; + + default: + ASSERT(0); + } + } +} + +static void +set_components(struct tegra_2d_surface_color *dst, + uint32_t x, + uint32_t y, + uint32_t z, + uint32_t w) +{ + int i; + + for (i=0; i<dst->num_planes; ++i) + { + uint32_t value; + + switch (dst->planes[i].format) + { + case TEGRA_2D_FORMAT_A8R8G8B8: + value = (w & 0xff) << 24; + value |= (x & 0xff) << 16; + value |= (y & 0xff) << 8; + value |= (z & 0xff) << 0; + break; + + case TEGRA_2D_FORMAT_A8B8G8R8: + value = (w & 0xff) << 24; + value |= (z & 0xff) << 16; + value |= (y & 0xff) << 8; + value |= (x & 0xff) << 0; + break; + + case TEGRA_2D_FORMAT_R8G8B8A8: + value = (x & 0xff) << 24; + value |= (y & 0xff) << 16; + value |= (z & 0xff) << 8; + value |= (w & 0xff) << 0; + break; + + case TEGRA_2D_FORMAT_B8G8R8A8: + value = (z & 0xff) << 24; + value |= (y & 0xff) << 16; + value |= (x & 0xff) << 8; + value |= (w & 0xff) << 0; + break; + + case TEGRA_2D_FORMAT_A4R4G4B4: + value = ((w >> 4) & 0x0f) << 12; + value |= ((x >> 4) & 0x0f) << 8; + value |= ((y >> 4) & 0x0f) << 4; + value |= ((z >> 4) & 0x0f) << 0; + break; + + case TEGRA_2D_FORMAT_R4G4B4A4: + value = ((x >> 4) & 0x0f) << 12; + value |= ((y >> 4) & 0x0f) << 8; + value |= ((z >> 4) & 0x0f) << 4; + value |= ((w >> 4) & 0x0f) << 0; + break; + + case TEGRA_2D_FORMAT_R5G6B5: + value = ((x >> 3) & 0x1f) << 11; + value |= ((y >> 2) & 0x3f) << 5; + value |= ((z >> 3) & 0x1f) << 0; + break; + + case TEGRA_2D_FORMAT_A1R5G5B5: + value = ((w >> 3) & 0x1f) << 11; + value |= ((x >> 3) & 0x1f) << 6; + value |= ((y >> 3) & 0x1f) << 1; + value |= ((z >> 7) & 0x01) << 0; + break; + + case TEGRA_2D_FORMAT_Y8: + value = x & 0xff; + break; + + case TEGRA_2D_FORMAT_U8: + value = y & 0xff; + break; + + case TEGRA_2D_FORMAT_V8: + value = z & 0xff; + break; + + case TEGRA_2D_FORMAT_U8_V8: + ((uint8_t *) &value)[0] = y & 0xff; + ((uint8_t *) &value)[1] = z & 0xff; + break; + + case TEGRA_2D_FORMAT_V8_U8: + ((uint8_t *) &value)[0] = z & 0xff; + ((uint8_t *) &value)[1] = y & 0xff; + break; + + case TEGRA_2D_FORMAT_UYVY: + ((uint8_t *) &value)[0] = y & 0xff; + ((uint8_t *) &value)[1] = x & 0xff; + ((uint8_t *) &value)[2] = z & 0xff; + ((uint8_t *) &value)[3] = x & 0xff; + break; + + case TEGRA_2D_FORMAT_VYUY: + ((uint8_t *) &value)[0] = z & 0xff; + ((uint8_t *) &value)[1] = x & 0xff; + ((uint8_t *) &value)[2] = y & 0xff; + ((uint8_t *) &value)[3] = x & 0xff; + break; + + case TEGRA_2D_FORMAT_YUYV: + ((uint8_t *) &value)[0] = x & 0xff; + ((uint8_t *) &value)[1] = y & 0xff; + ((uint8_t *) &value)[2] = x & 0xff; + ((uint8_t *) &value)[3] = z & 0xff; + break; + + case TEGRA_2D_FORMAT_YVYU: + ((uint8_t *) &value)[0] = x & 0xff; + ((uint8_t *) &value)[1] = z & 0xff; + ((uint8_t *) &value)[2] = x & 0xff; + ((uint8_t *) &value)[3] = y & 0xff; + break; + + default: + ASSERT(0); + } + + dst->planes[i].value = value; + } +} + +void +color_to_rgba(const struct tegra_2d_surface_color *src, + uint32_t *r, + uint32_t *g, + uint32_t *b, + uint32_t *a) +{ + ASSERT(src); + ASSERT(r && g && b && a); + + if (TEGRA_2D_FORMAT_IS_YUV(src->planes[0].format)) + { + uint32_t y, u, v; + y = 0; + u = 0; + v = 0; + + get_components(src, &y, &u, &v, NULL); + yuv_to_rgb(r, g, b, y, u, v); + *a = 255; + } + else + { + get_components(src, r, g, b, a); + } +} + +void +color_from_rgba(struct tegra_2d_surface_color *dst, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a) +{ + ASSERT(dst); + + if (TEGRA_2D_FORMAT_IS_YUV(dst->planes[0].format)) + { + uint32_t y, u, v; + + rgb_to_yuv(&y, &u, &v, r, g, b); + set_components(dst, y, u, v, 255); + } + else + { + set_components(dst, r, g, b, a); + } +} + +const char * +format_to_str(enum tegra_2d_format format) +{ + switch (format) + { + #define CASE(f) case TEGRA_2D_FORMAT_##f: return #f + CASE(A8R8G8B8); + CASE(A8B8G8R8); + CASE(R8G8B8A8); + CASE(B8G8R8A8); + CASE(A4R4G4B4); + CASE(R4G4B4A4); + CASE(R5G6B5); + CASE(A1R5G5B5); + CASE(Y8); + CASE(U8); + CASE(V8); + CASE(U8_V8); + CASE(V8_U8); + CASE(UYVY); + CASE(VYUY); + CASE(YUYV); + CASE(YVYU); + #undef CASE + + default: + return "unknown"; + } +} diff --git a/tegra/2d/tegra_2d_color.h b/tegra/2d/tegra_2d_color.h new file mode 100644 index 0000000..aceef6a --- /dev/null +++ b/tegra/2d/tegra_2d_color.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_COLOR_H +#define TEGRA_2D_COLOR_H + +void +color_convert(struct tegra_2d_surface_color *dst, + const struct tegra_2d_surface_color *src); + +void +color_to_rgba(const struct tegra_2d_surface_color *src, + uint32_t *r, + uint32_t *g, + uint32_t *b, + uint32_t *a); + +void +color_from_rgba(struct tegra_2d_surface_color *dst, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a); + +const char * +format_to_str(enum tegra_2d_format format); + +#endif // TEGRA_2D_COLOR_H diff --git a/tegra/2d/tegra_2d_context.c b/tegra/2d/tegra_2d_context.c new file mode 100644 index 0000000..d03d7d5 --- /dev/null +++ b/tegra/2d/tegra_2d_context.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include "tegra_2d.h" +#include "tegra_2d_context.h" +#include "tegra_2d_util.h" + +struct tegra_2d_ictx * +open2d(int fd) +{ + int i; + struct tegra_2d_ictx *ctx; + + ctx = malloc(sizeof(struct tegra_2d_ictx)); + if (ctx == NULL) + return NULL; + + ctx->base.log_enable = 0; + ctx->base.dump_enable = 0; + ctx->base.dump_counter = 0; + ctx->base.dump_prefix[0] = 0; + ctx->device = NULL; + ctx->channel = NULL; + ctx->stream = NULL; + tegra_fence_clear(&ctx->pre_fence); + tegra_fence_clear(&ctx->post_fence); + + ctx->device = tegra_device_create(fd); + if (ctx->device == NULL) + goto fail; + + ctx->channel = tegra_channel_open(ctx->device, TEGRADRM_MODULEID_2D); + if (ctx->channel == NULL) + goto fail; + + ctx->stream = tegra_stream_create(ctx->channel); + if (ctx->stream == NULL) + goto fail; + + for (i=0; i<TEGRA_2D_MAX_PLANES; ++i) + { + g2fill_init(&ctx->g2fill[i]); + g2copy_init(&ctx->g2copy[i]); + frcopy_init(&ctx->frcopy[i]); + } + + sbcopy_init(&ctx->sbcopy); + + return ctx; + +fail: + close2d(ctx); + return NULL; +} + +void +close2d(struct tegra_2d_ictx *ctx) +{ + ASSERT(ctx); + + tegra_stream_destroy(ctx->stream); + tegra_channel_close(ctx->channel); + tegra_device_destroy(ctx->device); + + free(ctx); +} + +int +begin2d(struct tegra_2d_ictx *ctx, + const struct tegra_fence *fence) +{ + ASSERT(ctx); + + if (fence != NULL) + tegra_fence_copy(&ctx->pre_fence, fence); + else + tegra_fence_clear(&ctx->pre_fence); + + return TEGRA_2D_OK; +} + +int +flush2d(struct tegra_2d_ictx *ctx) +{ + int result; + + ASSERT(ctx); + + result = tegra_stream_flush(ctx->stream, &ctx->post_fence); + + if (result != 0) + return TEGRA_2D_STREAM_FAILURE; + + return TEGRA_2D_OK; +} + +int +end2d(struct tegra_2d_ictx *ctx, + struct tegra_fence *fence) +{ + int result; + + ASSERT(ctx); + + result = flush2d(ctx); + + if (result != 0) + return result; + + if (fence != NULL) + tegra_fence_copy(fence, &ctx->post_fence); + else + tegra_fence_wait(ctx->channel, &ctx->post_fence); + + return TEGRA_2D_OK; +} diff --git a/tegra/2d/tegra_2d_context.h b/tegra/2d/tegra_2d_context.h new file mode 100644 index 0000000..703f23b --- /dev/null +++ b/tegra/2d/tegra_2d_context.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_CONTEXT_H +#define TEGRA_2D_CONTEXT_H + +#include "tegra_drmif.h" +#include "tegra_2d_g2fill.h" +#include "tegra_2d_g2copy.h" +#include "tegra_2d_frcopy.h" +#include "tegra_2d_sbcopy.h" + +struct tegra_2d_ictx +{ + struct tegra_2d_context base; + struct tegra_device *device; + struct tegra_channel *channel; + struct tegra_stream *stream; + struct tegra_fence pre_fence; + struct tegra_fence post_fence; + struct tegra_2d_g2fill g2fill[TEGRA_2D_MAX_PLANES]; + struct tegra_2d_g2copy g2copy[TEGRA_2D_MAX_PLANES]; + struct tegra_2d_frcopy frcopy[TEGRA_2D_MAX_PLANES]; + struct tegra_2d_sbcopy sbcopy; +}; + +struct tegra_2d_ictx * +open2d(int fd); + +void +close2d(struct tegra_2d_ictx *ctx); + +int +begin2d(struct tegra_2d_ictx *ctx, + const struct tegra_fence *fence); + +int +flush2d(struct tegra_2d_ictx *ctx); + +int +end2d(struct tegra_2d_ictx *ctx, + struct tegra_fence *fence); + +#endif // TEGRA_2D_CONTEXT_H diff --git a/tegra/2d/tegra_2d_copy.c b/tegra/2d/tegra_2d_copy.c new file mode 100644 index 0000000..a659b5b --- /dev/null +++ b/tegra/2d/tegra_2d_copy.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include "tegra_2d.h" +#include "tegra_2d_context.h" +#include "tegra_2d_copy.h" +#include "tegra_2d_surface.h" +#include "tegra_2d_util.h" +#include "tegra_2d_g2copy.h" +#include "tegra_2d_frcopy.h" +#include "tegra_2d_sbcopy.h" + +static int +copy_area(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface_area *dst_area, + const struct tegra_2d_surface_area *src_area, + enum tegra_2d_transform transform) +{ + int i; + int result = -1; + uint32_t num_words = 0; + uint32_t num_relocs = 0; + + ASSERT(dst_area->surface->num_planes == src_area->surface->num_planes); + + ctx->sbcopy.is_valid = 0; + + for (i=0; i<dst_area->surface->num_planes; ++i) + { + result = frcopy_set(&ctx->frcopy[i], + &dst_area->planes[i], + &src_area->planes[i], + transform); + if (result == TEGRA_2D_OK) + { + num_words += frcopy_num_words(&ctx->frcopy[i]); + num_relocs += frcopy_num_relocs(&ctx->frcopy[i]); + continue; + } + + result = g2copy_set(&ctx->g2copy[i], + &dst_area->planes[i], + &src_area->planes[i], + transform); + if (result == TEGRA_2D_OK) + { + num_words += g2copy_num_words(&ctx->g2copy[i]); + num_relocs += g2copy_num_relocs(&ctx->g2copy[i]); + continue; + } + + break; + } + + if (result != TEGRA_2D_OK) + { + result = sbcopy_set(&ctx->sbcopy, + dst_area, + src_area, + transform); + if (result != TEGRA_2D_OK) + return TEGRA_2D_UNSUPPORTED_BLIT; + + num_words = sbcopy_num_words(&ctx->sbcopy); + num_relocs = sbcopy_num_relocs(&ctx->sbcopy); + } + + if (ctx->base.log_enable) + { + if (ctx->sbcopy.is_valid) + { + sbcopy_dump(&ctx->sbcopy); + } + else + { + for (i=0; i<dst_area->surface->num_planes; ++i) + { + if (ctx->frcopy[i].is_valid) + frcopy_dump(&ctx->frcopy[i]); + else + g2copy_dump(&ctx->g2copy[i]); + } + } + } + + result = tegra_stream_begin(ctx->stream, + num_words, + &ctx->pre_fence, + tegra_fence_is_valid(&ctx->pre_fence) ? + 1 : 0, + 0, + num_relocs, + 0); + if (result != 0) + return TEGRA_2D_STREAM_FAILURE; + + if (ctx->sbcopy.is_valid) + { + sbcopy_dispatch(&ctx->sbcopy, ctx->stream); + } + else + { + for (i=0; i<dst_area->surface->num_planes; ++i) + { + if (ctx->frcopy[i].is_valid) + frcopy_dispatch(&ctx->frcopy[i], ctx->stream); + else + g2copy_dispatch(&ctx->g2copy[i], ctx->stream); + } + } + + tegra_stream_end(ctx->stream); + + return TEGRA_2D_OK; +} + +int +copy2d(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface *src, + const struct tegra_2d_rect *dst_rect, + const struct tegra_2d_rect *src_rect, + enum tegra_2d_transform transform) +{ + int result; + struct tegra_2d_rect vdst_rect; + struct tegra_2d_rect vsrc_rect; + struct tegra_2d_surface_area dst_area; + struct tegra_2d_surface_area src_area; + + ASSERT(ctx); + + if (dst == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + if (src == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + if (dst_rect == NULL) + { + vdst_rect.left = 0; + vdst_rect.top = 0; + vdst_rect.right = dst->planes[0].width; + vdst_rect.bottom = dst->planes[0].height; + } + else + { + result = validate_rect(dst, dst_rect); + if (result != TEGRA_2D_OK) + return result; + + vdst_rect = *dst_rect; + } + + if (src_rect == NULL) + { + vsrc_rect.left = 0; + vsrc_rect.top = 0; + vsrc_rect.right = src->planes[0].width; + vsrc_rect.bottom = src->planes[0].height; + } + else + { + result = validate_rect(src, src_rect); + if (result != TEGRA_2D_OK) + return result; + + vsrc_rect = *src_rect; + } + + compute_surface_area(&dst_area, dst, &vdst_rect); + compute_surface_area(&src_area, src, &vsrc_rect); + + if (ctx->base.dump_enable) + dump_src(ctx, src); + + result = copy_area(ctx, &dst_area, &src_area, transform); + if (result != TEGRA_2D_OK) + return result; + + if (ctx->base.dump_enable) + dump_dst(ctx, dst); + + return TEGRA_2D_OK; +} diff --git a/tegra/2d/tegra_2d_copy.h b/tegra/2d/tegra_2d_copy.h new file mode 100644 index 0000000..b307245 --- /dev/null +++ b/tegra/2d/tegra_2d_copy.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_COPY_H +#define TEGRA_2D_COPY_H + +int +copy2d(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface *src, + const struct tegra_2d_rect *dst_rect, + const struct tegra_2d_rect *src_rect, + enum tegra_2d_transform transform); + +#endif // TEGRA_2D_COPY_H diff --git a/tegra/2d/tegra_2d_fill.c b/tegra/2d/tegra_2d_fill.c new file mode 100644 index 0000000..8186b56 --- /dev/null +++ b/tegra/2d/tegra_2d_fill.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include "tegra_2d.h" +#include "tegra_2d_context.h" +#include "tegra_2d_fill.h" +#include "tegra_2d_color.h" +#include "tegra_2d_surface.h" +#include "tegra_2d_util.h" + +static int +fill_area(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface_area *dst_area, + const struct tegra_2d_surface_color *color) +{ + int i; + int result; + uint32_t num_words = 0; + uint32_t num_relocs = 0; + + for (i=0; i<dst_area->surface->num_planes; ++i) + { + ASSERT(dst_area->planes[i].plane->format == color->planes[i].format); + + result = g2fill_set(&ctx->g2fill[i], + &dst_area->planes[i], + &color->planes[i]); + if (result != TEGRA_2D_OK) + return result; + + num_words += g2fill_num_words(&ctx->g2fill[i]); + num_relocs += g2fill_num_relocs(&ctx->g2fill[i]); + } + + if (ctx->base.log_enable) + { + for (i=0; i<dst_area->surface->num_planes; ++i) + g2fill_dump(&ctx->g2fill[i]); + } + + result = tegra_stream_begin(ctx->stream, + num_words, + &ctx->pre_fence, + tegra_fence_is_valid(&ctx->pre_fence) ? + 1 : 0, + 0, + num_relocs, + 0); + if (result != 0) + return TEGRA_2D_STREAM_FAILURE; + + for (i=0; i<dst_area->surface->num_planes; ++i) + g2fill_dispatch(&ctx->g2fill[i], ctx->stream); + + tegra_stream_end(ctx->stream); + + return TEGRA_2D_OK; +} + +int +fill2d(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface_color *color, + const struct tegra_2d_rect *dst_rect) +{ + int i; + int result; + struct tegra_2d_rect vdst_rect; + struct tegra_2d_surface_color vcolor; + struct tegra_2d_surface_area dst_area; + + ASSERT(ctx); + + if (dst == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + if (color == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + if (dst_rect == NULL) + { + vdst_rect.left = 0; + vdst_rect.top = 0; + vdst_rect.right = dst->planes[0].width; + vdst_rect.bottom = dst->planes[0].height; + } + else + { + result = validate_rect(dst, dst_rect); + if (result != TEGRA_2D_OK) + return result; + + vdst_rect = *dst_rect; + } + + vcolor.num_planes = dst->num_planes; + for (i=0; i<vcolor.num_planes; ++i) + vcolor.planes[i].format = dst->planes[i].format; + + color_convert(&vcolor, color); + + compute_surface_area(&dst_area, dst, &vdst_rect); + + result = fill_area(ctx, &dst_area, &vcolor); + if (result != TEGRA_2D_OK) + return result; + + if (ctx->base.dump_enable) + dump_dst(ctx, dst); + + return TEGRA_2D_OK; +} diff --git a/tegra/2d/tegra_2d_fill.h b/tegra/2d/tegra_2d_fill.h new file mode 100644 index 0000000..1d52baa --- /dev/null +++ b/tegra/2d/tegra_2d_fill.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_FILL_H +#define TEGRA_2D_FILL_H + +int +fill2d(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface_color *color, + const struct tegra_2d_rect *dst_rect); + +#endif // TEGRA_2D_FILL_H diff --git a/tegra/2d/tegra_2d_frcopy.c b/tegra/2d/tegra_2d_frcopy.c new file mode 100644 index 0000000..991d29d --- /dev/null +++ b/tegra/2d/tegra_2d_frcopy.c @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include "tegra_drmif.h" +#include "class_ids.h" +#include "tegra_2d_frcopy.h" +#include "tegra_2d_reg_g2sb.h" +#include "tegra_2d_reg_host.h" + +uint32_t +frcopy_num_words(const struct tegra_2d_frcopy *hw) +{ + return 1 + sizeof(hw->block) / sizeof(uint32_t); +} + +uint32_t +frcopy_num_relocs(const struct tegra_2d_frcopy *hw) +{ + return 2; +} + +void +frcopy_init(struct tegra_2d_frcopy *hw) +{ + ASSERT(hw); + + hw->is_valid = 0; + + GR2D_RESET(trigger); + GR2D_RESET(cmdsel); + GR2D_RESET(controlsecond); + GR2D_RESET(controlmain); + GR2D_RESET(tilemode); + GR2D_RESET(dstba); + GR2D_RESET(dstst); + GR2D_RESET(srcba); + GR2D_RESET(srcst); + GR2D_RESET(srcsize); + + OPCODE_MASK2(op1, + trigger, + cmdsel); + OPCODE_MASK2(op2, + controlsecond, + controlmain); + OPCODE_NONINCR(op3, tilemode, 1); + OPCODE_MASK5(op4, + dstba, + dstst, + srcba, + srcst, + srcsize); + + GR2D_VAL(trigger, trigger, gr2d_srcsize_r()); + GR2D_DEF(cmdsel, sbor2d, g2); + GR2D_DEF(controlsecond, fr_mode, src_dst_copy); + GR2D_DEF(controlsecond, fr_readwait, enable); + GR2D_DEF(controlmain, cmdt, bitblt); +} + +static uint32_t +compute_offset(const struct tegra_2d_plane *plane, + uint32_t xpos, + uint32_t ypos) +{ + uint32_t offset; + uint32_t bytes_per_pixel = TEGRA_2D_FORMAT_BYTES(plane->format); + uint32_t pixels_per_line = plane->pitch / bytes_per_pixel; + + if (plane->layout == TEGRA_2D_LAYOUT_LINEAR) + { + offset = ypos * plane->pitch; + offset += xpos * bytes_per_pixel; + } + else + { + uint32_t xb = xpos * bytes_per_pixel; + offset = 16 * pixels_per_line * (ypos / 16); + offset += 256 * (xb / 16); + offset += 16 * (ypos % 16); + offset += xb % 16; + } + + return plane->mem_offset + offset; +} + +int +frcopy_set(struct tegra_2d_frcopy *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_area *src, + enum tegra_2d_transform transform) +{ + uint32_t block_size; + uint32_t align_mask; + uint32_t dst_xpos = dst->xpos; + uint32_t dst_ypos = dst->ypos; + uint32_t src_xpos = src->xpos; + uint32_t src_ypos = src->ypos; + uint32_t src_width = src->width; + uint32_t src_height = src->height; + + ASSERT(hw); + + hw->is_valid = 0; + + if (dst->plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + if (src->plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + if (src_width > 4096 || src_height > 4096) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (src->plane->format != dst->plane->format) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (!equal_size_area(src, dst, transform)) + return TEGRA_2D_UNSUPPORTED_BLIT; + + hw->dst_handle = dst->plane->mem_handle; + hw->dst_offset = compute_offset(dst->plane, dst_xpos, dst_ypos); + hw->src_handle = src->plane->mem_handle; + hw->src_offset = compute_offset(src->plane, src_xpos, src_ypos); + + switch (transform) + { + #define CASE(transform, v) \ + case TEGRA_2D_TRANSFORM_##transform: \ + GR2D_DEF(controlsecond, fr_type, v); \ + break + CASE(IDENTITY, identity); + CASE(ROT_90, rot_90); + CASE(ROT_180, rot_180); + CASE(ROT_270, rot_270); + CASE(FLIP_X, flip_x); + CASE(FLIP_Y, flip_y); + CASE(TRANSPOSE, trans_lr); + CASE(INV_TRANSPOSE, trans_rl); + #undef CASE + default: + ASSERT(0); + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + switch (TEGRA_2D_FORMAT_BITS(dst->plane->format)) + { + #define CASE(v) \ + case v: \ + GR2D_DEF(controlmain, dstcd, bpp##v); \ + block_size = 128 / v; \ + break + CASE(8); + CASE(16); + CASE(32); + #undef CASE + default: + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + align_mask = block_size - 1; + #define CHECK_ALIGNMENT(v) ((((uint32_t) v) & align_mask) != 0) + if (CHECK_ALIGNMENT(src_width) || + CHECK_ALIGNMENT(src_height) || + CHECK_ALIGNMENT(src_xpos) || + CHECK_ALIGNMENT(src_ypos) || + CHECK_ALIGNMENT(dst_xpos) || + CHECK_ALIGNMENT(dst_ypos)) + return TEGRA_2D_UNSUPPORTED_BLIT; + #undef CHECK_ALIGNMENT + + GR2D_DEF(controlmain, srccd, same); + + if (dst->plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, dst_wr_tile_mode, tiled); + else + GR2D_DEF(tilemode, dst_wr_tile_mode, linear); + + if (src->plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, src_y_tile_mode, tiled); + else + GR2D_DEF(tilemode, src_y_tile_mode, linear); + + GR2D_VAL(dstst, dsts, dst->plane->pitch); + GR2D_VAL(srcst, srcs, src->plane->pitch); + GR2D_VAL(srcsize, srcwidth, src_width - 1); + GR2D_VAL(srcsize, srcheight, src_height - 1); + + hw->is_valid = 1; + return TEGRA_2D_OK; +} + +void +frcopy_dispatch(const struct tegra_2d_frcopy *hw, + struct tegra_stream *stream) +{ + ASSERT(hw); + ASSERT(hw->is_valid); + ASSERT(stream); + + tegra_stream_push_setclass(stream, NV_GRAPHICS_2D_CLASS_ID); + + tegra_stream_push_words(stream, + &hw->block, + sizeof(hw->block) / sizeof(uint32_t), + 2, + tegra_reloc(&hw->block.dstba, + hw->dst_handle, + hw->dst_offset), + tegra_reloc(&hw->block.srcba, + hw->src_handle, + hw->src_offset)); +} + +void +frcopy_dump(const struct tegra_2d_frcopy *hw) +{ + char buffer[1024]; + int offset = 0; + int space = ARRAY_SIZE(buffer); + + ASSERT(hw); + + offset = snprintf(buffer, space, "G2 Copy:\n"); + + #define PRINT(reg) \ + offset += snprintf(buffer + offset, \ + MAX(0, space - offset), \ + "%18s: 0x%08x\n", \ + #reg, \ + hw->block.reg) + + PRINT(op1); + PRINT(trigger); + PRINT(cmdsel); + PRINT(op2); + PRINT(controlsecond); + PRINT(controlmain); + PRINT(op3); + PRINT(tilemode); + PRINT(op4); + PRINT(dstba); + PRINT(dstst); + PRINT(srcba); + PRINT(srcst); + PRINT(srcsize); + + #undef PRINT + + LOG("%s", buffer); +} diff --git a/tegra/2d/tegra_2d_frcopy.h b/tegra/2d/tegra_2d_frcopy.h new file mode 100644 index 0000000..f0ca115 --- /dev/null +++ b/tegra/2d/tegra_2d_frcopy.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_FRCOPY_H +#define TEGRA_2D_FRCOPY_H + +#include <stdint.h> +#include "tegra_2d.h" +#include "tegra_2d_util.h" + +struct tegra_2d_frcopy +{ + struct tegra_2d_frcopy_block + { + uint32_t op1; + uint32_t trigger; + uint32_t cmdsel; + + uint32_t op2; + uint32_t controlsecond; + uint32_t controlmain; + + uint32_t op3; + uint32_t tilemode; + + uint32_t op4; + uint32_t dstba; + uint32_t dstst; + uint32_t srcba; + uint32_t srcst; + uint32_t srcsize; + } block; + int is_valid; + struct tegra_bo *dst_handle; + struct tegra_bo *src_handle; + int dst_offset; + int src_offset; +}; + +uint32_t +frcopy_num_words(const struct tegra_2d_frcopy *hw); + +uint32_t +frcopy_num_relocs(const struct tegra_2d_frcopy *hw); + +void +frcopy_init(struct tegra_2d_frcopy *hw); + +int +frcopy_set(struct tegra_2d_frcopy *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_area *src, + enum tegra_2d_transform transform); + +void +frcopy_dispatch(const struct tegra_2d_frcopy *hw, + struct tegra_stream *stream); + +void +frcopy_dump(const struct tegra_2d_frcopy *hw); + +#endif // TEGRA_2D_FRCOPY_H diff --git a/tegra/2d/tegra_2d_g2copy.c b/tegra/2d/tegra_2d_g2copy.c new file mode 100644 index 0000000..9dccf25 --- /dev/null +++ b/tegra/2d/tegra_2d_g2copy.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include "tegra_drmif.h" +#include "class_ids.h" +#include "tegra_2d_g2copy.h" +#include "tegra_2d_reg_g2sb.h" +#include "tegra_2d_reg_host.h" + +uint32_t +g2copy_num_words(const struct tegra_2d_g2copy *hw) +{ + return 1 + sizeof(hw->block) / sizeof(uint32_t); +} + +uint32_t +g2copy_num_relocs(const struct tegra_2d_g2copy *hw) +{ + return 2; +} + +void +g2copy_init(struct tegra_2d_g2copy *hw) +{ + ASSERT(hw); + + hw->is_valid = 0; + + GR2D_RESET(trigger); + GR2D_RESET(cmdsel); + GR2D_RESET(controlsecond); + GR2D_RESET(controlmain); + GR2D_RESET(ropfade); + GR2D_RESET(tilemode); + GR2D_RESET(dstba); + GR2D_RESET(dstst); + GR2D_RESET(srcba); + GR2D_RESET(srcst); + GR2D_RESET(dstsize); + GR2D_RESET(srcps); + GR2D_RESET(dstps); + + OPCODE_MASK2(op1, + trigger, + cmdsel); + OPCODE_MASK3(op2, + controlsecond, + controlmain, + ropfade); + OPCODE_NONINCR(op3, tilemode, 1); + OPCODE_MASK7(op4, + dstba, + dstst, + srcba, + srcst, + dstsize, + srcps, + dstps); + + GR2D_VAL(trigger, trigger, gr2d_dstps_r()); + GR2D_DEF(cmdsel, sbor2d, g2); + GR2D_DEF(controlmain, cmdt, bitblt); + GR2D_VAL(ropfade, rop, 0xCC); +} + +int +g2copy_set(struct tegra_2d_g2copy *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_area *src, + enum tegra_2d_transform transform) +{ + int transpose; + int flip_x; + int flip_y; + uint32_t max_width; + uint32_t dst_xpos = dst->xpos; + uint32_t dst_ypos = dst->ypos; + uint32_t dst_width = dst->width; + uint32_t dst_height = dst->height; + uint32_t src_xpos = src->xpos; + uint32_t src_ypos = src->ypos; + + ASSERT(hw); + ASSERT(dst); + ASSERT(src); + + hw->is_valid = 0; + + if (dst->plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + if (src->plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + if (src->plane->format != dst->plane->format) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (!equal_size_area(src, dst, transform)) + return TEGRA_2D_UNSUPPORTED_BLIT; + + hw->dst_handle = dst->plane->mem_handle; + hw->dst_offset = dst->plane->mem_offset; + hw->src_handle = src->plane->mem_handle; + hw->src_offset = src->plane->mem_offset; + + switch (transform) + { + #define CASE(transform, t, fx, fy) \ + case TEGRA_2D_TRANSFORM_##transform: \ + transpose = t; \ + flip_x = fx; \ + flip_y = fy; \ + break + CASE(IDENTITY, 0, 0, 0); + CASE(ROT_90, 1, 0, 1); + CASE(ROT_180, 0, 1, 1); + CASE(ROT_270, 1, 1, 0); + CASE(FLIP_X, 0, 1, 0); + CASE(FLIP_Y, 0, 0, 1); + CASE(TRANSPOSE, 1, 0, 0); + CASE(INV_TRANSPOSE, 1, 1, 1); + #undef CASE + default: + ASSERT(0); + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + if (flip_x) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (transpose) + GR2D_DEF(controlmain, xytdw, enable); + else + GR2D_DEF(controlmain, xytdw, disable); + + switch (TEGRA_2D_FORMAT_BITS(dst->plane->format)) + { + #define CASE(v, max) \ + case v: \ + GR2D_DEF(controlmain, dstcd, bpp##v); \ + max_width = max; \ + break + CASE(8, 32760); + CASE(16, 16384); + CASE(32, 8192); + #undef CASE + default: + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + if (dst_width > max_width) + return TEGRA_2D_UNSUPPORTED_BLIT; + + GR2D_DEF(controlmain, srccd, same); + + if (dst->plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, dst_wr_tile_mode, tiled); + else + GR2D_DEF(tilemode, dst_wr_tile_mode, linear); + + if (src->plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, src_y_tile_mode, tiled); + else + GR2D_DEF(tilemode, src_y_tile_mode, linear); + + GR2D_VAL(dstst, dsts, dst->plane->pitch); + GR2D_VAL(srcst, srcs, src->plane->pitch); + GR2D_VAL(dstsize, dstwidth, dst_width); + GR2D_VAL(dstsize, dstheight, dst_height); + GR2D_VAL(srcps, srcx, src_xpos); + GR2D_VAL(srcps, srcy, src_ypos); + GR2D_VAL(dstps, dstx, dst_xpos); + if (flip_y) + { + GR2D_DEF(controlmain, yflip, enable); + GR2D_VAL(dstps, dsty, dst_ypos + dst_height - 1); + } + else + { + GR2D_DEF(controlmain, yflip, disable); + GR2D_VAL(dstps, dsty, dst_ypos); + } + + hw->is_valid = 1; + return TEGRA_2D_OK; +} + +void +g2copy_dispatch(const struct tegra_2d_g2copy *hw, + struct tegra_stream *stream) +{ + ASSERT(hw); + ASSERT(hw->is_valid); + ASSERT(stream); + + tegra_stream_push_setclass(stream, NV_GRAPHICS_2D_CLASS_ID); + + tegra_stream_push_words(stream, + &hw->block, + sizeof(hw->block) / sizeof(uint32_t), + 2, + tegra_reloc(&hw->block.dstba, + hw->dst_handle, + hw->dst_offset), + tegra_reloc(&hw->block.srcba, + hw->src_handle, + hw->src_offset)); +} + +void +g2copy_dump(const struct tegra_2d_g2copy *hw) +{ + char buffer[1024]; + int offset = 0; + int space = ARRAY_SIZE(buffer); + + ASSERT(hw); + + offset = snprintf(buffer, space, "G2 Copy:\n"); + + #define PRINT(reg) \ + offset += snprintf(buffer + offset, \ + MAX(0, space - offset), \ + "%18s: 0x%08x\n", \ + #reg, \ + hw->block.reg) + + PRINT(op1); + PRINT(trigger); + PRINT(cmdsel); + PRINT(op2); + PRINT(controlsecond); + PRINT(controlmain); + PRINT(ropfade); + PRINT(op3); + PRINT(tilemode); + PRINT(op4); + PRINT(dstba); + PRINT(dstst); + PRINT(srcba); + PRINT(srcst); + PRINT(dstsize); + PRINT(srcps); + PRINT(dstps); + + #undef PRINT + + LOG("%s", buffer); +} diff --git a/tegra/2d/tegra_2d_g2copy.h b/tegra/2d/tegra_2d_g2copy.h new file mode 100644 index 0000000..22f79bc --- /dev/null +++ b/tegra/2d/tegra_2d_g2copy.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_G2COPY_H +#define TEGRA_2D_G2COPY_H + +#include <stdint.h> +#include "tegra_2d.h" +#include "tegra_2d_util.h" + +struct tegra_2d_g2copy +{ + struct tegra_2d_g2copy_block + { + uint32_t op1; + uint32_t trigger; + uint32_t cmdsel; + + uint32_t op2; + uint32_t controlsecond; + uint32_t controlmain; + uint32_t ropfade; + + uint32_t op3; + uint32_t tilemode; + + uint32_t op4; + uint32_t dstba; + uint32_t dstst; + uint32_t srcba; + uint32_t srcst; + uint32_t dstsize; + uint32_t srcps; + uint32_t dstps; + } block; + int is_valid; + struct tegra_bo *dst_handle; + struct tegra_bo *src_handle; + int dst_offset; + int src_offset; +}; + +uint32_t +g2copy_num_words(const struct tegra_2d_g2copy *hw); + +uint32_t +g2copy_num_relocs(const struct tegra_2d_g2copy *hw); + +void +g2copy_init(struct tegra_2d_g2copy *hw); + +int +g2copy_set(struct tegra_2d_g2copy *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_area *src, + enum tegra_2d_transform transform); + +void +g2copy_dispatch(const struct tegra_2d_g2copy *hw, + struct tegra_stream *stream); + +void +g2copy_dump(const struct tegra_2d_g2copy *hw); + +#endif // TEGRA_2D_G2COPY_H diff --git a/tegra/2d/tegra_2d_g2fill.c b/tegra/2d/tegra_2d_g2fill.c new file mode 100644 index 0000000..91987c0 --- /dev/null +++ b/tegra/2d/tegra_2d_g2fill.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include "tegra_drmif.h" +#include "class_ids.h" +#include "tegra_2d_g2fill.h" +#include "tegra_2d_reg_g2sb.h" +#include "tegra_2d_reg_host.h" + +uint32_t +g2fill_num_words(const struct tegra_2d_g2fill *hw) +{ + return 1 + (sizeof(hw->block) / sizeof(uint32_t)); +} + +uint32_t +g2fill_num_relocs(const struct tegra_2d_g2fill *hw) +{ + return 1; +} + +void +g2fill_init(struct tegra_2d_g2fill *hw) +{ + ASSERT(hw); + + hw->is_valid = 0; + + GR2D_RESET(trigger); + GR2D_RESET(cmdsel); + GR2D_RESET(controlsecond); + GR2D_RESET(controlmain); + GR2D_RESET(ropfade); + GR2D_RESET(dstba); + GR2D_RESET(dstst); + GR2D_RESET(srcfgc); + GR2D_RESET(dstsize); + GR2D_RESET(dstps); + + OPCODE_MASK2(op1, + trigger, + cmdsel); + OPCODE_MASK3(op2, + controlsecond, + controlmain, + ropfade); + OPCODE_MASK5(op3, + dstba, + dstst, + srcfgc, + dstsize, + dstps); + + GR2D_VAL(trigger, trigger, gr2d_dstps_r()); + GR2D_DEF(cmdsel, sbor2d, g2); + GR2D_DEF(controlmain, cmdt, bitblt); + GR2D_DEF(controlmain, turbofill, enable); + GR2D_DEF(controlmain, srcsld, enable); + GR2D_VAL(ropfade, rop, 0xCC); +} + +int +g2fill_set(struct tegra_2d_g2fill *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_color *color) +{ + int max_width; + uint32_t dst_xpos = dst->xpos; + uint32_t dst_ypos = dst->ypos; + uint32_t dst_width = dst->width; + uint32_t dst_height = dst->height; + + ASSERT(hw); + ASSERT(dst); + ASSERT(color); + + hw->is_valid = 0; + + if (dst->plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + hw->dst_handle = dst->plane->mem_handle; + hw->dst_offset = dst->plane->mem_offset; + + switch (TEGRA_2D_FORMAT_BITS(dst->plane->format)) + { + #define CASE(v, max) \ + case v: \ + GR2D_DEF(controlmain, dstcd, bpp##v); \ + max_width = max; \ + break + CASE(8, 32760); + CASE(16, 16384); + CASE(32, 8192); + #undef CASE + default: + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + if (dst->width > max_width) + return TEGRA_2D_UNSUPPORTED_BLIT; + + GR2D_DEF(controlmain, srccd, same); + GR2D_VAL(dstst, dsts, dst->plane->pitch); + GR2D_VAL(srcfgc, srcfgc, color->value); + GR2D_VAL(dstsize, dstwidth, dst_width); + GR2D_VAL(dstsize, dstheight, dst_height); + GR2D_VAL(dstps, dstx, dst_xpos); + GR2D_VAL(dstps, dsty, dst_ypos); + + hw->is_valid = 1; + return TEGRA_2D_OK; +} + +void +g2fill_dispatch(const struct tegra_2d_g2fill *hw, + struct tegra_stream *stream) +{ + ASSERT(hw); + ASSERT(hw->is_valid); + ASSERT(stream); + + tegra_stream_push_setclass(stream, NV_GRAPHICS_2D_CLASS_ID); + + tegra_stream_push_words(stream, + &hw->block, + sizeof(hw->block) / sizeof(uint32_t), + 1, + tegra_reloc(&hw->block.dstba, + hw->dst_handle, + hw->dst_offset)); +} + +void +g2fill_dump(const struct tegra_2d_g2fill *hw) +{ + char buffer[1024]; + int offset = 0; + int space = ARRAY_SIZE(buffer); + + ASSERT(hw); + + offset = snprintf(buffer, space, "G2 Fill:\n"); + + #define PRINT(reg) \ + offset += snprintf(buffer + offset, \ + MAX(0, space - offset), \ + "%18s: 0x%08x\n", \ + #reg, \ + hw->block.reg) + + PRINT(op1); + PRINT(trigger); + PRINT(cmdsel); + PRINT(op2); + PRINT(controlsecond); + PRINT(controlmain); + PRINT(ropfade); + PRINT(op3); + PRINT(dstba); + PRINT(dstst); + PRINT(srcfgc); + PRINT(dstsize); + PRINT(dstps); + + #undef PRINT + + LOG("%s", buffer); +} diff --git a/tegra/2d/tegra_2d_g2fill.h b/tegra/2d/tegra_2d_g2fill.h new file mode 100644 index 0000000..e0715bd --- /dev/null +++ b/tegra/2d/tegra_2d_g2fill.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_G2FILL_H +#define TEGRA_2D_G2FILL_H + +#include <stdint.h> +#include "tegra_2d.h" +#include "tegra_2d_util.h" + +struct tegra_2d_g2fill +{ + struct tegra_2d_g2fill_block + { + uint32_t op1; + uint32_t trigger; + uint32_t cmdsel; + + uint32_t op2; + uint32_t controlsecond; + uint32_t controlmain; + uint32_t ropfade; + + uint32_t op3; + uint32_t dstba; + uint32_t dstst; + uint32_t srcfgc; + uint32_t dstsize; + uint32_t dstps; + } block; + int is_valid; + struct tegra_bo *dst_handle; + int dst_offset; +}; + +uint32_t +g2fill_num_words(const struct tegra_2d_g2fill *hw); + +uint32_t +g2fill_num_relocs(const struct tegra_2d_g2fill *hw); + +void +g2fill_init(struct tegra_2d_g2fill *hw); + +int +g2fill_set(struct tegra_2d_g2fill *hw, + const struct tegra_2d_plane_area *dst, + const struct tegra_2d_plane_color *color); + +void +g2fill_dispatch(const struct tegra_2d_g2fill *hw, + struct tegra_stream *stream); + +void +g2fill_dump(const struct tegra_2d_g2fill *hw); + +#endif // TEGRA_2D_G2FILL_H diff --git a/tegra/2d/tegra_2d_reg_g2sb.h b/tegra/2d/tegra_2d_reg_g2sb.h new file mode 100644 index 0000000..cbe09b0 --- /dev/null +++ b/tegra/2d/tegra_2d_reg_g2sb.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_REG_G2SB_H +#define TEGRA_2D_REG_G2SB_H + +#include <stdint.h> +#include "hw_gr2d.h" + +#define GR2D_RESET(reg) \ + hw->block.reg = gr2d_##reg##_reset_val_v() + +#define GR2D_VAL(reg, field, value) \ + hw->block.reg = (hw->block.reg & ~gr2d_##reg##_##field##_m()) \ + | gr2d_##reg##_##field##_f((value)) + +#define GR2D_DEF(reg, field, def) \ + hw->block.reg = (hw->block.reg & ~gr2d_##reg##_##field##_m()) \ + | gr2d_##reg##_##field##_f(gr2d_##reg##_##field##_##def##_v()) + +static inline uint32_t gr2d_controlmain_yflip_disable_v(void) +{ + return gr2d_controlmain_yflip_dsiable_v(); +} +static inline uint32_t gr2d_controlmain_turbofill_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_turbofill_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srccd_mono_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_srccd_same_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_xytdw_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_xytdw_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_srcdir_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_srcdir_enable_v(void) +{ + return 1; +} +static inline uint32_t gr2d_controlmain_dstdir_disable_v(void) +{ + return 0; +} +static inline uint32_t gr2d_controlmain_dstdir_enable_v(void) +{ + return 1; +} + +#endif // TEGRA_2D_REG_G2SB_H diff --git a/tegra/2d/tegra_2d_reg_host.h b/tegra/2d/tegra_2d_reg_host.h new file mode 100644 index 0000000..228d9bb --- /dev/null +++ b/tegra/2d/tegra_2d_reg_host.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_REG_HOST_H +#define TEGRA_2D_REG_HOST_H + +#include <stdint.h> +#include "host1x01_hardware.h" +#include "hw_gr2d.h" +#include "tegra_2d_util.h" + +#define ADDR(reg) gr2d_##reg##_r() + +#define OPCODE_INCR(word, reg, count) \ + hw->block.op = nvhost_opcode_nonincr(ADDR(reg), count) + +#define OPCODE_NONINCR(op, reg, count) \ + hw->block.op = nvhost_opcode_nonincr(ADDR(reg), count) + +#define OPCODE_MASK(op, addr, mask) \ + CT_ASSERT((mask) <= 0xffff); \ + hw->block.op = nvhost_opcode_mask(addr, mask) + +#define OPCODE_MASK2(op, reg0, reg1) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1))) + +#define OPCODE_MASK3(op, reg0, reg1, reg2) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) < ADDR(reg2)); \ + CT_ASSERT(ADDR(reg2) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg2))) + +#define OPCODE_MASK4(op, reg0, reg1, reg2, reg3) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) < ADDR(reg2)); \ + CT_ASSERT(ADDR(reg2) < ADDR(reg3)); \ + CT_ASSERT(ADDR(reg3) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg2)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg3))) + +#define OPCODE_MASK5(op, reg0, reg1, reg2, reg3, reg4) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) < ADDR(reg2)); \ + CT_ASSERT(ADDR(reg2) < ADDR(reg3)); \ + CT_ASSERT(ADDR(reg3) < ADDR(reg4)); \ + CT_ASSERT(ADDR(reg4) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg2)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg3)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg4))) + +#define OPCODE_MASK6(op, reg0, reg1, reg2, reg3, reg4, reg5) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) < ADDR(reg2)); \ + CT_ASSERT(ADDR(reg2) < ADDR(reg3)); \ + CT_ASSERT(ADDR(reg3) < ADDR(reg4)); \ + CT_ASSERT(ADDR(reg4) < ADDR(reg5)); \ + CT_ASSERT(ADDR(reg5) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg2)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg3)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg4)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg5))) + +#define OPCODE_MASK7(op, reg0, reg1, reg2, reg3, reg4, reg5, reg6) \ + CT_ASSERT(ADDR(reg0) < ADDR(reg1)); \ + CT_ASSERT(ADDR(reg1) < ADDR(reg2)); \ + CT_ASSERT(ADDR(reg2) < ADDR(reg3)); \ + CT_ASSERT(ADDR(reg3) < ADDR(reg4)); \ + CT_ASSERT(ADDR(reg4) < ADDR(reg5)); \ + CT_ASSERT(ADDR(reg5) < ADDR(reg6)); \ + CT_ASSERT(ADDR(reg6) - ADDR(reg0) < 16); \ + OPCODE_MASK(op, ADDR(reg0), \ + nvhost_mask2(ADDR(reg0), ADDR(reg0)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg1)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg2)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg3)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg4)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg5)) | \ + nvhost_mask2(ADDR(reg0), ADDR(reg6))) + +#endif // TEGRA_2D_REG_HOST_H diff --git a/tegra/2d/tegra_2d_sbcopy.c b/tegra/2d/tegra_2d_sbcopy.c new file mode 100644 index 0000000..9b858ff --- /dev/null +++ b/tegra/2d/tegra_2d_sbcopy.c @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include "tegra_drmif.h" +#include "class_ids.h" +#include "tegra_2d_sbcopy.h" +#include "tegra_2d_reg_g2sb.h" +#include "tegra_2d_reg_host.h" + +uint32_t +sbcopy_num_words(const struct tegra_2d_sbcopy *hw) +{ + return 1 + sizeof(hw->block) / sizeof(uint32_t); +} + +uint32_t +sbcopy_num_relocs(const struct tegra_2d_sbcopy *hw) +{ + return 4; +} + +void +sbcopy_init(struct tegra_2d_sbcopy *hw) +{ + ASSERT(hw); + + hw->is_valid = 0; + + GR2D_RESET(trigger); + GR2D_RESET(cmdsel); + GR2D_RESET(vdda); + GR2D_RESET(vddaini); + GR2D_RESET(hdda); + GR2D_RESET(hddainils); + GR2D_RESET(sbformat); + GR2D_RESET(controlsb); + GR2D_RESET(controlsecond); + GR2D_RESET(controlmain); + GR2D_RESET(dstba); + GR2D_RESET(tilemode); + GR2D_RESET(srcba_sb_surfbase); + GR2D_RESET(dstba_sb_surfbase); + GR2D_RESET(dstst); + GR2D_RESET(srcba); + GR2D_RESET(srcst); + GR2D_RESET(srcsize); + GR2D_RESET(dstsize); + + OPCODE_MASK6(op1, + trigger, + cmdsel, + vdda, + vddaini, + hdda, + hddainils); + OPCODE_MASK5(op2, + sbformat, + controlsb, + controlsecond, + controlmain, + dstba); + OPCODE_MASK3(op3, + tilemode, + srcba_sb_surfbase, + dstba_sb_surfbase); + OPCODE_MASK5(op4, + dstst, + srcba, + srcst, + srcsize, + dstsize); + + GR2D_VAL(trigger, trigger, gr2d_dstsize_r()); + GR2D_DEF(cmdsel, sbor2d, sb); + GR2D_DEF(controlmain, cmdt, bitblt); + GR2D_DEF(controlmain, srcdir, enable); + GR2D_DEF(controlmain, dstdir, enable); +} + +int +sbcopy_set(struct tegra_2d_sbcopy *hw, + const struct tegra_2d_surface_area *dst, + const struct tegra_2d_surface_area *src, + enum tegra_2d_transform transform) +{ + int transpose; + int flip_x; + int flip_y; + float inv_scale_x; + float inv_scale_y; + uint32_t dst_xpos = dst->planes[0].xpos; + uint32_t dst_ypos = dst->planes[0].ypos; + uint32_t dst_width = dst->planes[0].width; + uint32_t dst_height = dst->planes[0].height; + uint32_t src_xpos = src->planes[0].xpos; + uint32_t src_ypos = src->planes[0].ypos; + uint32_t src_width = src->planes[0].width; + uint32_t src_height = src->planes[0].height; + + ASSERT(hw); + ASSERT(dst); + ASSERT(src); + + hw->is_valid = 0; + + if (dst->surface->num_planes > 1) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (src->surface->num_planes > 1) + return TEGRA_2D_UNSUPPORTED_BLIT; + + if (dst->planes[0].plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + if (src->planes[0].plane->mem_handle == NULL) + return TEGRA_2D_INVALID_BUFFER; + + hw->dst_handle = dst->planes[0].plane->mem_handle; + hw->dst_offset = dst->planes[0].plane->mem_offset + + (TEGRA_2D_FORMAT_BYTES(dst->planes[0].plane->format) * + dst_xpos) + + (dst->planes[0].plane->pitch * dst_ypos); + hw->src_handle = src->planes[0].plane->mem_handle; + hw->src_offset = src->planes[0].plane->mem_offset + + (TEGRA_2D_FORMAT_BYTES(src->planes[0].plane->format) * + src_xpos) + + (src->planes[0].plane->pitch * src_ypos); + + switch (transform) + { + #define CASE(transform, t, fx, fy) \ + case TEGRA_2D_TRANSFORM_##transform: \ + transpose = t; \ + flip_x = fx; \ + flip_y = fy; \ + break + CASE(IDENTITY, 0, 0, 0); + CASE(ROT_90, 1, 0, 1); + CASE(ROT_180, 0, 1, 1); + CASE(ROT_270, 1, 1, 0); + CASE(FLIP_X, 0, 1, 0); + CASE(FLIP_Y, 0, 0, 1); + CASE(TRANSPOSE, 1, 0, 0); + CASE(INV_TRANSPOSE, 1, 1, 1); + #undef CASE + default: + ASSERT(0); + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + if (flip_x) + return TEGRA_2D_UNSUPPORTED_BLIT; + + #define FMT(sf, df) \ + (TEGRA_2D_FORMAT_ID(sf) | (TEGRA_2D_FORMAT_ID(df) << 16)) + + switch (FMT(src->planes[0].plane->format, dst->planes[0].plane->format)) + { + #define CASE(sf, df, sif, dif) \ + case FMT(TEGRA_2D_FORMAT_##sf, TEGRA_2D_FORMAT_##df): \ + GR2D_DEF(sbformat, sifmt, sif); \ + GR2D_DEF(sbformat, difmt, dif); \ + break + CASE(R5G6B5, R5G6B5, b5g6r5, b5g6r5); + CASE(R5G6B5, A1R5G5B5, b5g6r5, b5g6r5bs); + CASE(R5G6B5, A8B8G8R8, b5g6r5, r8g8b8a8); + CASE(R5G6B5, A8R8G8B8, b5g6r5, b8g8r8a8); + CASE(A1R5G5B5, R5G6B5, b5g6r5bs, b5g6r5); + CASE(A1R5G5B5, A1R5G5B5, b5g6r5bs, b5g6r5bs); + CASE(A1R5G5B5, A8B8G8R8, b5g6r5bs, r8g8b8a8); + CASE(A1R5G5B5, A8R8G8B8, b5g6r5bs, b8g8r8a8); + CASE(A8B8G8R8, R5G6B5, r8g8b8a8, b5g6r5); + CASE(A8B8G8R8, A1R5G5B5, r8g8b8a8, b5g6r5bs); + CASE(A8B8G8R8, A8B8G8R8, r8g8b8a8, r8g8b8a8); + CASE(A8B8G8R8, A8R8G8B8, r8g8b8a8, b8g8r8a8); + CASE(A8R8G8B8, R5G6B5, b8g8r8a8, b5g6r5); + CASE(A8R8G8B8, A1R5G5B5, b8g8r8a8, b5g6r5bs); + CASE(A8R8G8B8, A8B8G8R8, b8g8r8a8, r8g8b8a8); + CASE(A8R8G8B8, A8R8G8B8, b8g8r8a8, b8g8r8a8); + #undef CASE + default: + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + if (transpose) + { + GR2D_DEF(controlmain, xytdw, enable); + inv_scale_x = ((float) src->planes[0].width - 1) / + (dst->planes[0].height - 1); + inv_scale_y = ((float) src->planes[0].height - 1) / + (dst->planes[0].width - 1); + } + else + { + GR2D_DEF(controlmain, xytdw, disable); + inv_scale_x = ((float) src->planes[0].width - 1) / + (dst->planes[0].width - 1); + inv_scale_y = ((float) src->planes[0].height - 1) / + (dst->planes[0].height - 1); + } + + #define CHECK_SCALE(inv) \ + if (inv > 64.0f || inv < 1.0f/4096.0f) \ + return TEGRA_2D_UNSUPPORTED_BLIT; + CHECK_SCALE(inv_scale_x); + CHECK_SCALE(inv_scale_y); + #undef CHECK_SCALE + + GR2D_DEF(controlsb, discsc, disable); + + if (inv_scale_x == 1.0f) + GR2D_DEF(controlsb, hftype, disable); + else if (inv_scale_x < 1.0f) + GR2D_DEF(controlsb, hftype, interp); + else if (inv_scale_x < 1.3f) + GR2D_DEF(controlsb, hftype, lpf1); + else if (inv_scale_x < 2.0f) + GR2D_DEF(controlsb, hftype, lpf3); + else + GR2D_DEF(controlsb, hftype, lpf6); + + if (inv_scale_y == 1.0f) + { + GR2D_DEF(controlsb, vfen, disable); + } + else + { + GR2D_DEF(controlsb, vfen, enable); + + if (inv_scale_y < 1.0f) + GR2D_DEF(controlsb, vftype, interp); + else if (inv_scale_y < 1.3f) + GR2D_DEF(controlsb, vftype, avg25_interp75); + else if (inv_scale_y < 2.0f) + GR2D_DEF(controlsb, vftype, avg50_interp50); + else + GR2D_DEF(controlsb, vftype, avg); + } + + if (flip_y) + { + GR2D_DEF(controlmain, yflip, enable); + hw->dst_offset += dst->planes[0].plane->pitch * + (dst->planes[0].height - 1); + } + else + { + GR2D_DEF(controlmain, yflip, disable); + } + + switch (TEGRA_2D_FORMAT_BITS(dst->planes[0].plane->format)) + { + #define CASE(v) \ + case v: \ + GR2D_DEF(controlmain, dstcd, bpp##v); \ + break + CASE(8); + CASE(16); + CASE(32); + #undef CASE + default: + return TEGRA_2D_UNSUPPORTED_BLIT; + } + + GR2D_VAL(vdda, vdstep, FLOAT_TO_FIXED_6_12(inv_scale_y)); + GR2D_VAL(vddaini, vdtini, FLOAT_TO_FIXED_0_8(src->planes[0].ypos)); + GR2D_VAL(hdda, hdstep, FLOAT_TO_FIXED_6_12(inv_scale_x)); + GR2D_VAL(hddainils, hdini, FLOAT_TO_FIXED_0_8(src->planes[0].xpos)); + + + if (dst->planes[0].plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, dst_wr_tile_mode, tiled); + else + GR2D_DEF(tilemode, dst_wr_tile_mode, linear); + + if (src->planes[0].plane->layout == TEGRA_2D_LAYOUT_TILED) + GR2D_DEF(tilemode, src_y_tile_mode, tiled); + else + GR2D_DEF(tilemode, src_y_tile_mode, linear); + + GR2D_VAL(dstst, dsts, dst->planes[0].plane->pitch); + GR2D_VAL(srcst, srcs, src->planes[0].plane->pitch); + GR2D_VAL(srcsize, srcwidth, src_width); + GR2D_VAL(srcsize, srcheight, src_height - 1); + GR2D_VAL(dstsize, dstwidth, dst_width); + GR2D_VAL(dstsize, dstheight, dst_height - 1); + + hw->is_valid = 1; + return TEGRA_2D_OK; +} + +void +sbcopy_dispatch(const struct tegra_2d_sbcopy *hw, + struct tegra_stream *stream) +{ + ASSERT(hw); + ASSERT(hw->is_valid); + ASSERT(stream); + + tegra_stream_push_setclass(stream, NV_GRAPHICS_2D_SB_CLASS_ID); + + tegra_stream_push_words(stream, + &hw->block, + sizeof(hw->block) / sizeof(uint32_t), + 4, + tegra_reloc(&hw->block.dstba, + hw->dst_handle, + hw->dst_offset), + tegra_reloc(&hw->block.srcba_sb_surfbase, + hw->src_handle, + hw->src_offset), + tegra_reloc(&hw->block.dstba_sb_surfbase, + hw->dst_handle, + hw->dst_offset), + tegra_reloc(&hw->block.srcba, + hw->src_handle, + hw->src_offset)); +} + +void +sbcopy_dump(const struct tegra_2d_sbcopy *hw) +{ + char buffer[1024]; + int offset = 0; + int space = ARRAY_SIZE(buffer); + + ASSERT(hw); + + offset = snprintf(buffer, space, "G2 Copy:\n"); + + #define PRINT(reg) \ + offset += snprintf(buffer + offset, \ + MAX(0, space - offset), \ + "%18s: 0x%08x\n", \ + #reg, \ + hw->block.reg) + + PRINT(op1); + PRINT(trigger); + PRINT(cmdsel); + PRINT(vdda); + PRINT(vddaini); + PRINT(hdda); + PRINT(hddainils); + PRINT(op2); + PRINT(sbformat); + PRINT(controlsb); + PRINT(controlsecond); + PRINT(controlmain); + PRINT(dstba); + PRINT(op3); + PRINT(tilemode); + PRINT(srcba_sb_surfbase); + PRINT(dstba_sb_surfbase); + PRINT(op4); + PRINT(dstst); + PRINT(srcba); + PRINT(srcst); + PRINT(srcsize); + PRINT(dstsize); + + #undef PRINT + + LOG("%s", buffer); +} diff --git a/tegra/2d/tegra_2d_sbcopy.h b/tegra/2d/tegra_2d_sbcopy.h new file mode 100644 index 0000000..38abad2 --- /dev/null +++ b/tegra/2d/tegra_2d_sbcopy.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_SBCOPY_H +#define TEGRA_2D_SBCOPY_H + +#include <stdint.h> +#include "tegra_2d.h" +#include "tegra_2d_util.h" + +struct tegra_2d_sbcopy +{ + struct tegra_2d_sbcopy_block + { + uint32_t op1; + uint32_t trigger; + uint32_t cmdsel; + uint32_t vdda; + uint32_t vddaini; + uint32_t hdda; + uint32_t hddainils; + + uint32_t op2; + uint32_t sbformat; + uint32_t controlsb; + uint32_t controlsecond; + uint32_t controlmain; + uint32_t dstba; + + uint32_t op3; + uint32_t tilemode; + uint32_t srcba_sb_surfbase; + uint32_t dstba_sb_surfbase; + + uint32_t op4; + uint32_t dstst; + uint32_t srcba; + uint32_t srcst; + uint32_t srcsize; + uint32_t dstsize; + } block; + int is_valid; + struct tegra_bo *dst_handle; + struct tegra_bo *src_handle; + int dst_offset; + int src_offset; +}; + +uint32_t +sbcopy_num_words(const struct tegra_2d_sbcopy *hw); + +uint32_t +sbcopy_num_relocs(const struct tegra_2d_sbcopy *hw); + +void +sbcopy_init(struct tegra_2d_sbcopy *hw); + +int +sbcopy_set(struct tegra_2d_sbcopy *hw, + const struct tegra_2d_surface_area *dst, + const struct tegra_2d_surface_area *src, + enum tegra_2d_transform transform); + +void +sbcopy_dispatch(const struct tegra_2d_sbcopy *hw, + struct tegra_stream *stream); + +void +sbcopy_dump(const struct tegra_2d_sbcopy *hw); + +#endif // TEGRA_2D_SBCOPY_H diff --git a/tegra/2d/tegra_2d_surface.c b/tegra/2d/tegra_2d_surface.c new file mode 100644 index 0000000..5d64adc --- /dev/null +++ b/tegra/2d/tegra_2d_surface.c @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include <stdio.h> +#include "tegra_2d.h" +#include "tegra_2d_context.h" +#include "tegra_2d_surface.h" +#include "tegra_2d_color.h" +#include "tegra_2d_util.h" + +int +compute_requirements(const struct tegra_2d_plane *plane, + uint32_t *num_bytes, + uint32_t *alignment, + uint32_t *pitch) +{ + uint32_t num_lines; + uint32_t bytes_per_line; + uint32_t bytes_per_pixel; + + if (plane == NULL || + num_bytes == NULL || + alignment == NULL || + pitch == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + num_lines = plane->height + 1; + bytes_per_pixel = TEGRA_2D_FORMAT_BYTES(plane->format); + + if (plane->layout == TEGRA_2D_LAYOUT_LINEAR) + { + *alignment = 16; + bytes_per_line = ROUND_UP(plane->width * bytes_per_pixel, 32); + } + else + { + *alignment = 256; + bytes_per_line = ROUND_UP(plane->width * bytes_per_pixel, 64); + } + + *pitch = bytes_per_line; + *num_bytes = (num_lines * bytes_per_line) + bytes_per_pixel; + + return TEGRA_2D_OK; +} + +int +allocate_surface(struct tegra_2d_ictx *ctx, + struct tegra_2d_surface *surface) +{ + int i; + int result; + uint32_t num_bytes = 0; + uint32_t alignment = 1; + struct tegra_bo *mem_handle; + + ASSERT(ctx); + + if (surface == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + for (i=0; i<surface->num_planes; ++i) + { + uint32_t nb, a, p; + struct tegra_2d_plane *plane = &surface->planes[i]; + + result = compute_requirements(plane, &nb, &a, &p); + if (result != TEGRA_2D_OK) + return result; + + num_bytes = ROUND_UP(num_bytes, a); + + plane->pitch = p; + plane->mem_handle = NULL; + plane->mem_offset = num_bytes; + + num_bytes += nb; + alignment = MAX(alignment, a); + } + + mem_handle = tegra_bo_allocate(ctx->device, + num_bytes, + alignment); + if (mem_handle == NULL) + return TEGRA_2D_MEMORY_FAILURE; + + for (i=0; i<surface->num_planes; ++i) + surface->planes[i].mem_handle = mem_handle; + + return TEGRA_2D_OK; +} + +void +free_surface(struct tegra_2d_ictx *ctx, + struct tegra_2d_surface *surface) +{ + int i; + + ASSERT(ctx); + + if (surface == NULL) + return; + + tegra_bo_free(surface->planes[0].mem_handle); + + for (i=0; i<surface->num_planes; ++i) + surface->planes[i].mem_handle = NULL; +} + +int +dump_surface(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *surface, + const char *filename) +{ + int i; + int result; + FILE *fp; + + ASSERT(ctx); + + if (surface == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + if (filename == NULL) + return TEGRA_2D_INVALID_PARAMETER; + + LOG("Dumping: %s\n", filename); + + fp = fopen(filename, "wb"); + if (fp == NULL) + return TEGRA_2D_FILE_FAILURE; + + result = TEGRA_2D_OK; + + for (i=0; i<surface->num_planes; ++i) + { + void *ptr; + uint8_t *src; + uint32_t bytes_per_pixel; + uint32_t bytes_per_line; + uint32_t num_lines; + const struct tegra_2d_plane *plane = &surface->planes[i]; + + if (plane->mem_handle == NULL) + { + result = TEGRA_2D_INVALID_BUFFER; + goto exit; + } + + bytes_per_pixel = TEGRA_2D_FORMAT_BYTES(plane->format); + bytes_per_line = plane->width * bytes_per_pixel; + num_lines = plane->height; + + ptr = tegra_bo_map(plane->mem_handle); + if (ptr == NULL) + { + result = TEGRA_2D_MEMORY_FAILURE; + goto exit; + } + + src = ((uint8_t *) ptr) + plane->mem_offset; + + while (num_lines > 0) + { + fwrite(src, 1, bytes_per_line, fp); + src += plane->pitch; + --num_lines; + } + + tegra_bo_unmap(plane->mem_handle); + } + +exit: + fclose(fp); + return result; +} + +static void +compute_dump_name(char *buffer, + size_t buffer_size, + const struct tegra_2d_surface *surface, + const char *label, + const char *prefix, + int counter) +{ + int i; + int offset = 0; + int space = buffer_size; + + offset += snprintf(buffer + offset, + MAX(0, space - offset), + "%stegra_2d_%d_%s_", + prefix, + counter, + label); + + for (i=0; i<surface->num_planes; ++i) + { + offset += snprintf(buffer + offset, + MAX(0, space - offset), + "%s%dx%dx%s", + i == 0 ? "" : "-", + surface->planes[i].width, + surface->planes[i].height, + format_to_str(surface->planes[i].format)); + } + + offset += snprintf(buffer + offset, + MAX(0, space - offset), + ".raw"); +} + +void +dump_src(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *src) +{ + char filename[FILENAME_MAX]; + + ASSERT(ctx); + ASSERT(src); + + compute_dump_name(filename, + ARRAY_SIZE(filename), + src, + "src", + ctx->base.dump_prefix, + ctx->base.dump_counter); + + tegra_fence_wait(ctx->channel, &ctx->pre_fence); + + dump_surface(ctx, src, filename); +} + +void +dump_dst(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst) +{ + char filename[FILENAME_MAX]; + + ASSERT(ctx); + ASSERT(dst); + + compute_dump_name(filename, + ARRAY_SIZE(filename), + dst, + "dst", + ctx->base.dump_prefix, + ctx->base.dump_counter); + + flush2d(ctx); + tegra_fence_wait(ctx->channel, &ctx->post_fence); + + dump_surface(ctx, dst, filename); + + ++ctx->base.dump_counter; +} diff --git a/tegra/2d/tegra_2d_surface.h b/tegra/2d/tegra_2d_surface.h new file mode 100644 index 0000000..8e3dc1e --- /dev/null +++ b/tegra/2d/tegra_2d_surface.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_SURFACE_H +#define TEGRA_2D_SURFACE_H + +int +compute_requirements(const struct tegra_2d_plane *plane, + uint32_t *num_bytes, + uint32_t *alignment, + uint32_t *pitch); + +int +allocate_surface(struct tegra_2d_ictx *ctx, + struct tegra_2d_surface *surface); + +void +free_surface(struct tegra_2d_ictx *ctx, + struct tegra_2d_surface *surface); + +int +dump_surface(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *surface, + const char *filename); + +void +dump_src(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *src); + +void +dump_dst(struct tegra_2d_ictx *ctx, + const struct tegra_2d_surface *dst); + +#endif // TEGRA_2D_SURFACE_H diff --git a/tegra/2d/tegra_2d_util.c b/tegra/2d/tegra_2d_util.c new file mode 100644 index 0000000..ea2e407 --- /dev/null +++ b/tegra/2d/tegra_2d_util.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include "tegra_2d.h" +#include "tegra_2d_util.h" + +void +compute_surface_area(struct tegra_2d_surface_area *area, + const struct tegra_2d_surface *surface, + const struct tegra_2d_rect *rect) +{ + int i; + float xpos; + float ypos; + float width; + float height; + + ASSERT(area); + ASSERT(surface); + ASSERT(rect); + + area->surface = surface; + + xpos = rect->left; + ypos = rect->top; + width = RECT_WIDTH(*rect); + height = RECT_HEIGHT(*rect); + + for (i=0; i<surface->num_planes; ++i) + { + const struct tegra_2d_plane *p = &surface->planes[i]; + struct tegra_2d_plane_area *pa = &area->planes[i]; + + pa->plane = p; + pa->xpos = (xpos * p->width) / surface->planes[0].width; + pa->ypos = (ypos * p->height) / surface->planes[0].height; + pa->width = (width * p->width) / surface->planes[0].width; + pa->height = (height * p->height) / surface->planes[0].height; + } +} + +int +validate_rect(const struct tegra_2d_surface *surface, + const struct tegra_2d_rect *rect) +{ + if (rect->left < 0 || + rect->left >= rect->right || + rect->top < 0 || + rect->top >= rect->bottom || + rect->right > surface->planes[0].width || + rect->bottom > surface->planes[0].height) + return TEGRA_2D_INVALID_RECT; + + return TEGRA_2D_OK; +} + +int +transform_swaps_xy(enum tegra_2d_transform transform) +{ + switch (transform) + { + case TEGRA_2D_TRANSFORM_ROT_90: + case TEGRA_2D_TRANSFORM_ROT_270: + case TEGRA_2D_TRANSFORM_TRANSPOSE: + case TEGRA_2D_TRANSFORM_INV_TRANSPOSE: + return 1; + default: + case TEGRA_2D_TRANSFORM_IDENTITY: + case TEGRA_2D_TRANSFORM_ROT_180: + case TEGRA_2D_TRANSFORM_FLIP_X: + case TEGRA_2D_TRANSFORM_FLIP_Y: + return 0; + } +} + +int +equal_size_area(const struct tegra_2d_plane_area *a, + const struct tegra_2d_plane_area *b, + enum tegra_2d_transform transform) +{ + #define CHECK(fa, fb) \ + if (fabs(fa - fb) >= 0.001f) \ + return 0 + + if (transform_swaps_xy(transform)) + { + CHECK(a->width, b->height); + CHECK(a->height, b->width); + } + else + { + CHECK(a->width, b->width); + CHECK(b->height, b->height); + } + + #undef CHECK + + return 1; +} + +const char * +result_to_str(enum tegra_2d_result result) +{ + switch (result) + { + #define CASE(r) case TEGRA_2D_##r: return #r + CASE(OK); + CASE(INVALID_PARAMETER); + CASE(INVALID_RECT); + CASE(INVALID_BUFFER); + CASE(UNSUPPORTED_BLIT); + CASE(MEMORY_FAILURE); + CASE(STREAM_FAILURE); + CASE(CHANNEL_FAILURE); + CASE(DEVICE_FAILURE); + CASE(FILE_FAILURE); + #undef CASE + + default: + return "unknown result"; + } +} diff --git a/tegra/2d/tegra_2d_util.h b/tegra/2d/tegra_2d_util.h new file mode 100644 index 0000000..70bd25a --- /dev/null +++ b/tegra/2d/tegra_2d_util.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_UTIL_H +#define TEGRA_2D_UTIL_H + +#include <assert.h> +#include <stdio.h> +#include <math.h> + +#define ASSERT assert +#define CT_ASSERT(x) ((void) sizeof(char[1 - 2*!(x)])) + +#define MIN(a, b) (a < b ? a : b) +#define MAX(a, b) (a > b ? a : b) + +#define CLAMP(x, l, h) (((x) < (l)) ? (l) : ((x) > (h) ? (h) : (x))) + +#define ROUND_UP(v, a) (v + (a - 1)) & ~(a - 1) + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define RECT_WIDTH(r) ((r).right - (r).left) +#define RECT_HEIGHT(r) ((r).bottom - (r).top) + +#define FLOAT_TO_FIXED_6_12(fp) (((int32_t) (fp * 4096.0f + 0.5f)) & ((1<<18)-1)) +#define FLOAT_TO_FIXED_0_8(fp) (((int32_t) (fp * 256.0f + 0.5f)) & ((1<<8)-1)) + +#define LOG(...) printf("[TEGRA_2D] " __VA_ARGS__) + +struct tegra_2d_plane_area +{ + const struct tegra_2d_plane *plane; + float xpos; + float ypos; + float width; + float height; +}; + +struct tegra_2d_surface_area +{ + const struct tegra_2d_surface *surface; + struct tegra_2d_plane_area planes[TEGRA_2D_MAX_PLANES]; +}; + +void +compute_surface_area(struct tegra_2d_surface_area *area, + const struct tegra_2d_surface *surface, + const struct tegra_2d_rect *rect); + +int +validate_rect(const struct tegra_2d_surface *surface, + const struct tegra_2d_rect *rect); + +int +equal_size_area(const struct tegra_2d_plane_area *a, + const struct tegra_2d_plane_area *b, + enum tegra_2d_transform transform); + +int +transform_swaps_xy(enum tegra_2d_transform transform); + +const char * +result_to_str(enum tegra_2d_result result); + +#endif // TEGRA_2D_UTIL_H diff --git a/tegra/Makefile.am b/tegra/Makefile.am index 72675e5..34a49d5 100644 --- a/tegra/Makefile.am +++ b/tegra/Makefile.am @@ -11,7 +11,18 @@ libdrm_tegra_la_LDFLAGS = -version-number 1:0:0 -no-undefined libdrm_tegra_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
libdrm_tegra_la_SOURCES = \ - tegra_drm.c + tegra_drm.c \ + 2d/tegra_2d_api.c \ + 2d/tegra_2d_color.c \ + 2d/tegra_2d_context.c \ + 2d/tegra_2d_copy.c \ + 2d/tegra_2d_fill.c \ + 2d/tegra_2d_frcopy.c \ + 2d/tegra_2d_g2copy.c \ + 2d/tegra_2d_g2fill.c \ + 2d/tegra_2d_sbcopy.c \ + 2d/tegra_2d_surface.c \ + 2d/tegra_2d_util.c
libdrm_tegracommonincludedir = ${includedir}/tegra libdrm_tegracommoninclude_HEADERS = \ diff --git a/tegra/tegra_2d.h b/tegra/tegra_2d.h new file mode 100644 index 0000000..a6d2f2f --- /dev/null +++ b/tegra/tegra_2d.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#ifndef TEGRA_2D_H +#define TEGRA_2D_H + +#include <stdint.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct tegra_fence; + +struct tegra_2d_context +{ + int log_enable; + int dump_enable; + int dump_counter; + char dump_prefix[FILENAME_MAX]; +}; + +struct tegra_2d_rect +{ + float left; + float top; + float right; + float bottom; +}; + +enum tegra_2d_layout +{ + TEGRA_2D_LAYOUT_LINEAR, + TEGRA_2D_LAYOUT_TILED, +}; + +#define TEGRA_2D_FORMAT(id, yuv, bpp) \ + ((id << 16) | (yuv << 8) | (bpp)) + +#define TEGRA_2D_FORMAT_BITS(f) \ + ((f) & 0xff) + +#define TEGRA_2D_FORMAT_BYTES(f) \ + (TEGRA_2D_FORMAT_BITS(f) >> 3) + +#define TEGRA_2D_FORMAT_IS_YUV(f) \ + (((f) >> 8) & 0xff) + +#define TEGRA_2D_FORMAT_ID(f) \ + (((f) >> 16) & 0xff) + +enum tegra_2d_format +{ + TEGRA_2D_FORMAT_A8R8G8B8 = TEGRA_2D_FORMAT( 1, 0, 32), + TEGRA_2D_FORMAT_A8B8G8R8 = TEGRA_2D_FORMAT( 2, 0, 32), + TEGRA_2D_FORMAT_R8G8B8A8 = TEGRA_2D_FORMAT( 3, 0, 32), + TEGRA_2D_FORMAT_B8G8R8A8 = TEGRA_2D_FORMAT( 4, 0, 32), + TEGRA_2D_FORMAT_A4R4G4B4 = TEGRA_2D_FORMAT( 5, 0, 16), + TEGRA_2D_FORMAT_R4G4B4A4 = TEGRA_2D_FORMAT( 6, 0, 16), + TEGRA_2D_FORMAT_R5G6B5 = TEGRA_2D_FORMAT( 7, 0, 16), + TEGRA_2D_FORMAT_A1R5G5B5 = TEGRA_2D_FORMAT( 8, 0, 16), + TEGRA_2D_FORMAT_Y8 = TEGRA_2D_FORMAT( 9, 1, 8), + TEGRA_2D_FORMAT_U8 = TEGRA_2D_FORMAT(10, 1, 8), + TEGRA_2D_FORMAT_V8 = TEGRA_2D_FORMAT(11, 1, 8), + TEGRA_2D_FORMAT_U8_V8 = TEGRA_2D_FORMAT(12, 1, 16), + TEGRA_2D_FORMAT_V8_U8 = TEGRA_2D_FORMAT(13, 1, 16), + TEGRA_2D_FORMAT_UYVY = TEGRA_2D_FORMAT(14, 1, 32), + TEGRA_2D_FORMAT_VYUY = TEGRA_2D_FORMAT(15, 1, 32), + TEGRA_2D_FORMAT_YUYV = TEGRA_2D_FORMAT(16, 1, 32), + TEGRA_2D_FORMAT_YVYU = TEGRA_2D_FORMAT(17, 1, 32), +}; + +enum tegra_2d_transform +{ + TEGRA_2D_TRANSFORM_IDENTITY, + TEGRA_2D_TRANSFORM_ROT_90, + TEGRA_2D_TRANSFORM_ROT_180, + TEGRA_2D_TRANSFORM_ROT_270, + TEGRA_2D_TRANSFORM_FLIP_X, + TEGRA_2D_TRANSFORM_FLIP_Y, + TEGRA_2D_TRANSFORM_TRANSPOSE, + TEGRA_2D_TRANSFORM_INV_TRANSPOSE +}; + +enum tegra_2d_result +{ + TEGRA_2D_OK, + TEGRA_2D_INVALID_PARAMETER, + TEGRA_2D_INVALID_RECT, + TEGRA_2D_INVALID_BUFFER, + TEGRA_2D_UNSUPPORTED_BLIT, + TEGRA_2D_MEMORY_FAILURE, + TEGRA_2D_STREAM_FAILURE, + TEGRA_2D_CHANNEL_FAILURE, + TEGRA_2D_DEVICE_FAILURE, + TEGRA_2D_FILE_FAILURE +}; + +struct tegra_2d_plane +{ + int width; + int height; + int pitch; + enum tegra_2d_format format; + enum tegra_2d_layout layout; + struct tegra_bo *mem_handle; + uint32_t mem_offset; +}; + +struct tegra_2d_plane_color +{ + uint32_t value; + enum tegra_2d_format format; +}; + +#define TEGRA_2D_MAX_PLANES 3 + +struct tegra_2d_surface +{ + int num_planes; + struct tegra_2d_plane planes[TEGRA_2D_MAX_PLANES]; +}; + +struct tegra_2d_surface_color +{ + int num_planes; + struct tegra_2d_plane_color planes[TEGRA_2D_MAX_PLANES]; +}; + +struct tegra_2d_context * +tegra_2d_open(int fd); + +void +tegra_2d_close(struct tegra_2d_context *ctx); + +int +tegra_2d_begin(struct tegra_2d_context *ctx, + const struct tegra_fence *fence); + +int +tegra_2d_end(struct tegra_2d_context *ctx, + struct tegra_fence *fence); + +int +tegra_2d_fill(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface_color *color, + const struct tegra_2d_rect *dst_rect); + +int +tegra_2d_copy(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *dst, + const struct tegra_2d_surface *src, + const struct tegra_2d_rect *dst_rect, + const struct tegra_2d_rect *src_rect, + enum tegra_2d_transform transform); + +int +tegra_2d_compute_requirements(const struct tegra_2d_plane *plane, + uint32_t *num_bytes, + uint32_t *alignment, + uint32_t *pitch); + +int +tegra_2d_allocate_surface(struct tegra_2d_context *ctx, + struct tegra_2d_surface *surface); + +void +tegra_2d_free_surface(struct tegra_2d_context *ctx, + struct tegra_2d_surface *surface); + +int +tegra_2d_dump_surface(struct tegra_2d_context *ctx, + const struct tegra_2d_surface *surface, + const char *filename); + +void +tegra_2d_color_convert(struct tegra_2d_surface_color *dst, + const struct tegra_2d_surface_color *src); + +void +tegra_2d_color_to_rgba(const struct tegra_2d_surface_color *src, + uint32_t *r, + uint32_t *g, + uint32_t *b, + uint32_t *a); + +void +tegra_2d_color_from_rgba(struct tegra_2d_surface_color *dst, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a); + +#ifdef __cplusplus +}; +#endif + +#endif // TEGRA_2D_H
I just skimmed the code of libdrm while I'm trying to understand the host1x driver. So below is what I found.
Mark On 12/13/2012 10:01 PM, Arto Meriläinen wrote:
From: Francis Hart fhart@nvidia.com
This patch introduces a simple 2d library on top of stream library.
Signed-off-by: Francis Hart fhart@nvidia.com
[...]
+void +g2fill_dispatch(const struct tegra_2d_g2fill *hw,
struct tegra_stream *stream)
+{
- ASSERT(hw);
- ASSERT(hw->is_valid);
- ASSERT(stream);
- tegra_stream_push_setclass(stream, NV_GRAPHICS_2D_CLASS_ID);
I think at the end of the "tegra_stream_begin", we already pushed a setclass opcode into the stream's active buffer. So why we need another one here?
- tegra_stream_push_words(stream,
&hw->block,
sizeof(hw->block) / sizeof(uint32_t),
1,
tegra_reloc(&hw->block.dstba,
hw->dst_handle,
hw->dst_offset));
+}
[...]
+#endif // TEGRA_2D_H
From: Francis Hart fhart@nvidia.com
This patch adds a test application for 2d library. The application performs 2d operations using the hardware and outputs the results into files.
Signed-off-by: Francis Hart fhart@nvidia.com --- configure.ac | 1 + tests/tegra/2d/Makefile.am | 13 ++ tests/tegra/2d/tegra_2d_test.c | 413 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 427 insertions(+) create mode 100644 tests/tegra/2d/Makefile.am create mode 100644 tests/tegra/2d/tegra_2d_test.c
diff --git a/configure.ac b/configure.ac index 36c55c7..b1170d3 100644 --- a/configure.ac +++ b/configure.ac @@ -376,6 +376,7 @@ AC_CONFIG_FILES([ tests/kmstest/Makefile tests/radeon/Makefile tests/vbltest/Makefile + tests/tegra/2d/Makefile include/Makefile include/drm/Makefile man/Makefile diff --git a/tests/tegra/2d/Makefile.am b/tests/tegra/2d/Makefile.am new file mode 100644 index 0000000..6967fbf --- /dev/null +++ b/tests/tegra/2d/Makefile.am @@ -0,0 +1,13 @@ +AM_CFLAGS = \ + -I $(top_srcdir)/include/drm \ + -I $(top_srcdir) + +LDADD = \ + $(top_builddir)/libdrm.la \ + $(top_builddir)/tegra/libdrm_tegra.la + +noinst_PROGRAMS = \ + tegra_2d_test + +tegra_2d_test_SOURCES = \ + tegra_2d_test.c diff --git a/tests/tegra/2d/tegra_2d_test.c b/tests/tegra/2d/tegra_2d_test.c new file mode 100644 index 0000000..11cc089 --- /dev/null +++ b/tests/tegra/2d/tegra_2d_test.c @@ -0,0 +1,413 @@ +/* + * Copyright (C) 2012 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: + * Francis Hart fhart@nvidia.com + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "tegra/tegra_drmif.h" +#include "tegra/tegra_2d.h" +#include "xf86drm.h" +#include "xf86drmMode.h" +#include "include/drm/drm_fourcc.h" + +static void +set_pixel_color(struct tegra_2d_surface *surface, + int x, + int y, + struct tegra_2d_surface_color *color) +{ + int i; + + for (i=0; i<surface->num_planes; ++i) + { + int px; + int py; + int offset; + uint32_t bytes_per_pixel; + const uint8_t *src; + uint8_t *dst; + void *ptr; + struct tegra_2d_plane *plane = &surface->planes[i]; + + bytes_per_pixel = TEGRA_2D_FORMAT_BYTES(plane->format); + + ptr = tegra_bo_map(plane->mem_handle); + if (ptr == NULL) + continue; + + px = (x * plane->width) / surface->planes[0].width; + py = (y * plane->height) / surface->planes[0].height; + + offset = (py * plane->pitch) + (px * bytes_per_pixel); + + src = (const uint8_t *) &color->planes[i].value; + dst = ((uint8_t *) ptr) + plane->mem_offset + offset; + + switch (bytes_per_pixel) + { + case 4: dst[3] = src[3]; + case 3: dst[2] = src[2]; + case 2: dst[1] = src[1]; + case 1: dst[0] = src[0]; + default: + break; + } + + tegra_bo_unmap(plane->mem_handle); + } +} + +static void +set_pixel_rgba(struct tegra_2d_surface *surface, + int x, + int y, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a) +{ + struct tegra_2d_surface_color color; + + color.num_planes = surface->num_planes; + color.planes[0].format = surface->planes[0].format; + color.planes[1].format = surface->planes[1].format; + color.planes[2].format = surface->planes[2].format; + + tegra_2d_color_from_rgba(&color, r, g, b, a); + + set_pixel_color(surface, x, y, &color); +} + +static void +clear_surface(struct tegra_2d_surface *surface, + uint32_t r, + uint32_t g, + uint32_t b, + uint32_t a) +{ + int x; + int y; + struct tegra_2d_surface_color color; + + color.num_planes = surface->num_planes; + color.planes[0].format = surface->planes[0].format; + color.planes[1].format = surface->planes[1].format; + color.planes[2].format = surface->planes[2].format; + + tegra_2d_color_from_rgba(&color, r, g, b, a); + + for (y=0; y<surface->planes[0].height; ++y) + for (x=0; x<surface->planes[0].width; ++x) + set_pixel_color(surface, x, y, &color); +} + +static int +test_fill(struct tegra_2d_context *ctx) +{ + int result; + struct tegra_2d_surface dst; + struct tegra_2d_surface_color color; + + memset(&dst, 0, sizeof(struct tegra_2d_surface)); + + dst.num_planes = 1; + dst.planes[0].width = 16; + dst.planes[0].height = 16; + dst.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + dst.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + + color.num_planes = 1; + color.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + color.planes[0].value = 0xFF00FFFF; + + result = tegra_2d_allocate_surface(ctx, &dst); + if (result != TEGRA_2D_OK) + goto exit; + + clear_surface(&dst, 255, 255, 0, 255); + + result = tegra_2d_begin(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_fill(ctx, &dst, &color, NULL); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_end(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + +exit: + tegra_2d_free_surface(ctx, &dst); + + return result == TEGRA_2D_OK ? 1 : 0; +} + +static int +test_copy(struct tegra_2d_context *ctx) +{ + int result; + struct tegra_2d_surface src; + struct tegra_2d_surface dst; + + memset(&dst, 0, sizeof(struct tegra_2d_surface)); + + src.num_planes = 3; + src.planes[0].width = 16; + src.planes[0].height = 16; + src.planes[0].format = TEGRA_2D_FORMAT_Y8; + src.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + src.planes[1].width = 8; + src.planes[1].height = 8; + src.planes[1].format = TEGRA_2D_FORMAT_U8; + src.planes[1].layout = TEGRA_2D_LAYOUT_LINEAR; + src.planes[2].width = 8; + src.planes[2].height = 8; + src.planes[2].format = TEGRA_2D_FORMAT_V8; + src.planes[2].layout = TEGRA_2D_LAYOUT_LINEAR; + + dst.num_planes = 3; + dst.planes[0].width = 16; + dst.planes[0].height = 16; + dst.planes[0].format = TEGRA_2D_FORMAT_Y8; + dst.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + dst.planes[1].width = 8; + dst.planes[1].height = 8; + dst.planes[1].format = TEGRA_2D_FORMAT_U8; + dst.planes[1].layout = TEGRA_2D_LAYOUT_LINEAR; + dst.planes[2].width = 8; + dst.planes[2].height = 8; + dst.planes[2].format = TEGRA_2D_FORMAT_V8; + dst.planes[2].layout = TEGRA_2D_LAYOUT_LINEAR; + + result = tegra_2d_allocate_surface(ctx, &src); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_allocate_surface(ctx, &dst); + if (result != TEGRA_2D_OK) + goto exit; + + clear_surface(&dst, 255, 255, 0, 255); + clear_surface(&src, 255, 0, 255, 255); + + set_pixel_rgba(&src, 1, 1, 255, 0, 0, 255); + set_pixel_rgba(&src, 2, 1, 0, 255, 0, 255); + set_pixel_rgba(&src, 1, 2, 0, 0, 255, 255); + + result = tegra_2d_begin(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_copy(ctx, + &dst, + &src, + NULL, + NULL, + TEGRA_2D_TRANSFORM_IDENTITY); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_end(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + +exit: + tegra_2d_free_surface(ctx, &src); + tegra_2d_free_surface(ctx, &dst); + + return result == TEGRA_2D_OK ? 1 : 0; +} + +static int +test_transform(struct tegra_2d_context *ctx) +{ + int result; + struct tegra_2d_surface src; + struct tegra_2d_surface dst; + + memset(&dst, 0, sizeof(struct tegra_2d_surface)); + + src.num_planes = 1; + src.planes[0].width = 10; + src.planes[0].height = 10; + src.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + src.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + + dst.num_planes = 1; + dst.planes[0].width = 10; + dst.planes[0].height = 10; + dst.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + dst.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + + result = tegra_2d_allocate_surface(ctx, &src); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_allocate_surface(ctx, &dst); + if (result != TEGRA_2D_OK) + goto exit; + + clear_surface(&dst, 255, 255, 0, 255); + clear_surface(&src, 255, 0, 255, 255); + + set_pixel_rgba(&src, 1, 1, 255, 0, 0, 255); + set_pixel_rgba(&src, 2, 1, 0, 255, 0, 255); + set_pixel_rgba(&src, 1, 2, 0, 0, 255, 255); + + result = tegra_2d_begin(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_copy(ctx, + &dst, + &src, + NULL, + NULL, + TEGRA_2D_TRANSFORM_ROT_90); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_end(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + +exit: + tegra_2d_free_surface(ctx, &src); + tegra_2d_free_surface(ctx, &dst); + + return result == TEGRA_2D_OK ? 1 : 0; +} + +static int +test_scale(struct tegra_2d_context *ctx) +{ + int result; + struct tegra_2d_surface src; + struct tegra_2d_surface dst; + + memset(&dst, 0, sizeof(struct tegra_2d_surface)); + + src.num_planes = 1; + src.planes[0].width = 10; + src.planes[0].height = 10; + src.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + src.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + + dst.num_planes = 1; + dst.planes[0].width = 20; + dst.planes[0].height = 20; + dst.planes[0].format = TEGRA_2D_FORMAT_A8R8G8B8; + dst.planes[0].layout = TEGRA_2D_LAYOUT_LINEAR; + + result = tegra_2d_allocate_surface(ctx, &src); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_allocate_surface(ctx, &dst); + if (result != TEGRA_2D_OK) + goto exit; + + clear_surface(&dst, 255, 255, 0, 255); + clear_surface(&src, 255, 255, 255, 255); + + set_pixel_rgba(&src, 1, 1, 255, 0, 0, 255); + set_pixel_rgba(&src, 2, 1, 0, 255, 0, 255); + set_pixel_rgba(&src, 1, 2, 0, 0, 255, 255); + + result = tegra_2d_begin(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_copy(ctx, + &dst, + &src, + NULL, + NULL, + TEGRA_2D_TRANSFORM_IDENTITY); + if (result != TEGRA_2D_OK) + goto exit; + + result = tegra_2d_end(ctx, NULL); + if (result != TEGRA_2D_OK) + goto exit; + +exit: + tegra_2d_free_surface(ctx, &src); + tegra_2d_free_surface(ctx, &dst); + + return result == TEGRA_2D_OK ? 1 : 0; +} + +int +main(int argc, + char *argv[]) +{ + int num_failures = 0; + struct tegra_2d_context *ctx; + int fd; + + fd = drmOpen("tegra", NULL); + if (fd < 0) { + ++num_failures; + goto exit; + } + + ctx = tegra_2d_open(fd); + if (ctx == NULL) + { + ++num_failures; + goto exit; + } + + ctx->log_enable = 1; + ctx->dump_enable = 1; + + if (test_fill(ctx) == 0) + ++num_failures; + + if (test_copy(ctx) == 0) + ++num_failures; + + if (test_transform(ctx) == 0) + ++num_failures; + + if (test_scale(ctx) == 0) + ++num_failures; + +exit: + tegra_2d_close(ctx); + + if (num_failures > 0) + printf("FAILED\n"); + else + printf("PASSED\n"); + + if (fd > 0) + drmClose(fd); + return EXIT_SUCCESS; +}
dri-devel@lists.freedesktop.org