summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2016-07-04 11:36:19 +0200
committerThierry Reding <treding@nvidia.com>2016-07-04 11:36:19 +0200
commit6155941e45bc244a523a9ca62b234e71365aff2d (patch)
treea94e585ba464e3488d2e00ec887f18c71e6ca875
parentf5002d2e7394af77ce459ce8c38de3fa4f06d135 (diff)
parent9a934c22c4e6d643823acaa80d8ef631ee34c637 (diff)
Merge branch 'staging/tegra' into staging/masterstaging/master
-rw-r--r--configure.ac14
-rw-r--r--src/gallium/Makefile.am5
-rw-r--r--src/gallium/auxiliary/target-helpers/drm_helper.h23
-rw-r--r--src/gallium/auxiliary/target-helpers/drm_helper_public.h3
-rw-r--r--src/gallium/drivers/tegra/Automake.inc11
-rw-r--r--src/gallium/drivers/tegra/Makefile.am17
-rw-r--r--src/gallium/drivers/tegra/Makefile.sources4
-rw-r--r--src/gallium/drivers/tegra/tegra_context.c962
-rw-r--r--src/gallium/drivers/tegra/tegra_context.h80
-rw-r--r--src/gallium/drivers/tegra/tegra_resource.c262
-rw-r--r--src/gallium/drivers/tegra/tegra_resource.h98
-rw-r--r--src/gallium/drivers/tegra/tegra_screen.c384
-rw-r--r--src/gallium/drivers/tegra/tegra_screen.h45
-rw-r--r--src/gallium/targets/dri/Makefile.am2
-rw-r--r--src/gallium/targets/dri/target.c10
-rw-r--r--src/gallium/targets/pipe-loader/Makefile.am16
-rw-r--r--src/gallium/targets/pipe-loader/pipe_tegra.c41
-rw-r--r--src/gallium/winsys/tegra/drm/Makefile.am11
-rw-r--r--src/gallium/winsys/tegra/drm/Makefile.sources2
-rw-r--r--src/gallium/winsys/tegra/drm/tegra_drm_public.h31
-rw-r--r--src/gallium/winsys/tegra/drm/tegra_drm_winsys.c40
21 files changed, 2060 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 8321e8eb21da..5cd1d9bd8cd5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,6 +75,7 @@ LIBDRM_INTEL_REQUIRED=2.4.61
LIBDRM_NVVIEUX_REQUIRED=2.4.66
LIBDRM_NOUVEAU_REQUIRED=2.4.66
LIBDRM_FREEDRENO_REQUIRED=2.4.67
+LIBDRM_TEGRA_REQUIRED=2.4.58
DRI2PROTO_REQUIRED=2.6
DRI3PROTO_REQUIRED=1.0
PRESENTPROTO_REQUIRED=1.0
@@ -971,7 +972,7 @@ GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast"
AC_ARG_WITH([gallium-drivers],
[AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@],
[comma delimited Gallium drivers list, e.g.
- "i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4,virgl"
+ "i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,tegra,vc4,virgl"
@<:@default=r300,r600,svga,swrast@:>@])],
[with_gallium_drivers="$withval"],
[with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"])
@@ -2429,6 +2430,12 @@ if test -n "$with_gallium_drivers"; then
gallium_require_drm "freedreno"
gallium_require_drm_loader
;;
+ xtegra)
+ HAVE_GALLIUM_TEGRA=yes
+ PKG_CHECK_MODULES([TEGRA], [libdrm_tegra >= $LIBDRM_TEGRA_REQUIRED])
+ gallium_require_drm "tegra"
+ gallium_require_drm_loader
+ ;;
xswrast)
HAVE_GALLIUM_SOFTPIPE=yes
if test "x$MESA_LLVM" = x1; then
@@ -2542,6 +2549,7 @@ AM_CONDITIONAL(HAVE_GALLIUM_RADEON_COMMON, test "x$HAVE_GALLIUM_R600" = xyes -o
"x$HAVE_GALLIUM_RADEONSI" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_NOUVEAU, test "x$HAVE_GALLIUM_NOUVEAU" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_FREEDRENO, test "x$HAVE_GALLIUM_FREEDRENO" = xyes)
+AM_CONDITIONAL(HAVE_GALLIUM_TEGRA, test "x$HAVE_GALLIUM_TEGRA" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_SOFTPIPE, test "x$HAVE_GALLIUM_SOFTPIPE" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_LLVMPIPE, test "x$HAVE_GALLIUM_LLVMPIPE" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_SWR, test "x$HAVE_GALLIUM_SWR" = xyes)
@@ -2682,6 +2690,9 @@ AC_CONFIG_FILES([Makefile
src/gallium/drivers/softpipe/Makefile
src/gallium/drivers/svga/Makefile
src/gallium/drivers/swr/Makefile
+ src/gallium/drivers/swr/avx/Makefile
+ src/gallium/drivers/swr/avx2/Makefile
+ src/gallium/drivers/tegra/Makefile
src/gallium/drivers/trace/Makefile
src/gallium/drivers/vc4/Makefile
src/gallium/drivers/virgl/Makefile
@@ -2724,6 +2735,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/winsys/sw/null/Makefile
src/gallium/winsys/sw/wrapper/Makefile
src/gallium/winsys/sw/xlib/Makefile
+ src/gallium/winsys/tegra/drm/Makefile
src/gallium/winsys/vc4/drm/Makefile
src/gallium/winsys/virgl/drm/Makefile
src/gallium/winsys/virgl/vtest/Makefile
diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am
index 34671ca88d50..c2fc47abf560 100644
--- a/src/gallium/Makefile.am
+++ b/src/gallium/Makefile.am
@@ -82,6 +82,11 @@ if HAVE_GALLIUM_SWR
SUBDIRS += drivers/swr
endif
+## tegra
+if HAVE_GALLIUM_TEGRA
+SUBDIRS += drivers/tegra winsys/tegra/drm
+endif
+
## vc4/rpi
if HAVE_GALLIUM_VC4
SUBDIRS += drivers/vc4 winsys/vc4/drm
diff --git a/src/gallium/auxiliary/target-helpers/drm_helper.h b/src/gallium/auxiliary/target-helpers/drm_helper.h
index 90820d3fe910..0d625f7b018f 100644
--- a/src/gallium/auxiliary/target-helpers/drm_helper.h
+++ b/src/gallium/auxiliary/target-helpers/drm_helper.h
@@ -266,5 +266,28 @@ pipe_vc4_create_screen(int fd)
#endif
+#ifdef GALLIUM_TEGRA
+#include "tegra/drm/tegra_drm_public.h"
+
+struct pipe_screen *
+pipe_tegra_create_screen(int fd)
+{
+ struct pipe_screen *screen;
+
+ screen = tegra_drm_screen_create(fd);
+
+ return screen ? debug_screen_wrap(screen) : NULL;
+}
+
+#else
+
+struct pipe_screen *
+pipe_tegra_create_screen(int fd)
+{
+ fprintf(stderr, "tegra: driver missing\n");
+ return NULL;
+}
+
+#endif
#endif /* DRM_HELPER_H */
diff --git a/src/gallium/auxiliary/target-helpers/drm_helper_public.h b/src/gallium/auxiliary/target-helpers/drm_helper_public.h
index d1f9382a6f97..5eb5f488f7f0 100644
--- a/src/gallium/auxiliary/target-helpers/drm_helper_public.h
+++ b/src/gallium/auxiliary/target-helpers/drm_helper_public.h
@@ -34,4 +34,7 @@ pipe_virgl_create_screen(int fd);
struct pipe_screen *
pipe_vc4_create_screen(int fd);
+struct pipe_screen *
+pipe_tegra_create_screen(int fd);
+
#endif /* _DRM_HELPER_PUBLIC_H */
diff --git a/src/gallium/drivers/tegra/Automake.inc b/src/gallium/drivers/tegra/Automake.inc
new file mode 100644
index 000000000000..f65281916245
--- /dev/null
+++ b/src/gallium/drivers/tegra/Automake.inc
@@ -0,0 +1,11 @@
+if HAVE_GALLIUM_TEGRA
+
+TARGET_DRIVERS += tegra
+TARGET_CPPFLAGS += -DGALLIUM_TEGRA
+TARGET_LIB_DEPS += \
+ $(top_builddir)/src/gallium/winsys/tegra/drm/libtegradrm.la \
+ $(top_builddir)/src/gallium/drivers/tegra/libtegra.la \
+ $(LIBDRM_LIBS) \
+ $(TEGRA_LIBS)
+
+endif
diff --git a/src/gallium/drivers/tegra/Makefile.am b/src/gallium/drivers/tegra/Makefile.am
new file mode 100644
index 000000000000..eb03df9bb2ed
--- /dev/null
+++ b/src/gallium/drivers/tegra/Makefile.am
@@ -0,0 +1,17 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+include Makefile.sources
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ $(GALLIUM_DRIVER_CFLAGS) \
+ $(LIBUDEV_CFLAGS) \
+ $(TEGRA_CFLAGS)
+
+noinst_LTLIBRARIES = libtegra.la
+
+libtegra_la_SOURCES = \
+ $(C_SOURCES)
+
+libtegra_la_LIBADD = \
+ $(LIBUDEV_LIBS)
diff --git a/src/gallium/drivers/tegra/Makefile.sources b/src/gallium/drivers/tegra/Makefile.sources
new file mode 100644
index 000000000000..978dd14667f5
--- /dev/null
+++ b/src/gallium/drivers/tegra/Makefile.sources
@@ -0,0 +1,4 @@
+C_SOURCES := \
+ tegra_context.c \
+ tegra_resource.c \
+ tegra_screen.c
diff --git a/src/gallium/drivers/tegra/tegra_context.c b/src/gallium/drivers/tegra/tegra_context.c
new file mode 100644
index 000000000000..389bc8bc6a59
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_context.c
@@ -0,0 +1,962 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include <stdlib.h>
+
+#include "util/u_debug.h"
+#include "util/u_inlines.h"
+
+#include "tegra/tegra_context.h"
+#include "tegra/tegra_resource.h"
+#include "tegra/tegra_screen.h"
+
+static void
+tegra_destroy(struct pipe_context *pcontext)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p)\n", __func__, pcontext);
+
+ context->gpu->destroy(context->gpu);
+ free(context);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_draw_vbo(struct pipe_context *pcontext,
+ const struct pipe_draw_info *pinfo)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_draw_info info;
+
+ debug_printf("> %s(pcontext=%p, pinfo=%p)\n", __func__, pcontext,
+ pinfo);
+ debug_printf(" pinfo:\n");
+ debug_printf(" indexed: %d\n", pinfo->indexed);
+ debug_printf(" mode: %x\n", pinfo->mode);
+ debug_printf(" start: %u\n", pinfo->start);
+ debug_printf(" count: %u\n", pinfo->count);
+
+ if (pinfo && pinfo->indirect) {
+ debug_printf(" unwrapping pipe_draw_info\n");
+ memcpy(&info, pinfo, sizeof(info));
+ info.indirect = tegra_resource_unwrap(info.indirect);
+ pinfo = &info;
+ }
+
+ context->gpu->draw_vbo(context->gpu, pinfo);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_blend_state(struct pipe_context *pcontext,
+ const struct pipe_blend_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_blend_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_blend_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_blend_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_blend_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_blend_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_sampler_state(struct pipe_context *pcontext,
+ const struct pipe_sampler_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_sampler_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_sampler_states(struct pipe_context *pcontext,
+ unsigned shader,
+ unsigned start_slot,
+ unsigned num_samplers,
+ void **samplers)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, shader=%u, start_slot=%u, num_samplers=%u, samplers=%p)\n",
+ __func__, pcontext, shader, start_slot, num_samplers,
+ samplers);
+
+ context->gpu->bind_sampler_states(context->gpu, shader, start_slot,
+ num_samplers, samplers);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_sampler_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_sampler_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_rasterizer_state(struct pipe_context *pcontext,
+ const struct pipe_rasterizer_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_rasterizer_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_rasterizer_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_rasterizer_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_rasterizer_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_rasterizer_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_depth_stencil_alpha_state(struct pipe_context *pcontext,
+ const struct pipe_depth_stencil_alpha_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_depth_stencil_alpha_state(context->gpu,
+ cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_depth_stencil_alpha_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_depth_stencil_alpha_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_depth_stencil_alpha_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_depth_stencil_alpha_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_fs_state(struct pipe_context *pcontext,
+ const struct pipe_shader_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_fs_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_fs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_fs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_fs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_fs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_vs_state(struct pipe_context *pcontext,
+ const struct pipe_shader_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_vs_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_vs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_vs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_vs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_vs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_gs_state(struct pipe_context *pcontext,
+ const struct pipe_shader_state *cso)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, cso=%p)\n", __func__, pcontext, cso);
+
+ so = context->gpu->create_gs_state(context->gpu, cso);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_gs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_gs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_gs_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_gs_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_create_vertex_elements_state(struct pipe_context *pcontext,
+ unsigned num_elements,
+ const struct pipe_vertex_element *elements)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ void *so;
+
+ debug_printf("> %s(pcontext=%p, num_elements=%u, elements=%p)\n",
+ __func__, pcontext, num_elements, elements);
+
+ so = context->gpu->create_vertex_elements_state(context->gpu,
+ num_elements,
+ elements);
+
+ debug_printf("< %s() = %p\n", __func__, so);
+ return so;
+}
+
+static void
+tegra_bind_vertex_elements_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->bind_vertex_elements_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_delete_vertex_elements_state(struct pipe_context *pcontext,
+ void *so)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, so=%p)\n", __func__, pcontext, so);
+
+ context->gpu->delete_vertex_elements_state(context->gpu, so);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_constant_buffer(struct pipe_context *pcontext,
+ uint shader,
+ uint index,
+ struct pipe_constant_buffer *buf)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_constant_buffer buffer;
+
+ debug_printf("> %s(pcontext=%p, shader=%u, index=%u, buf=%p)\n",
+ __func__, pcontext, shader, index, buf);
+
+ if (buf && buf->buffer) {
+ memcpy(&buffer, buf, sizeof(buffer));
+ debug_printf(" buffer: %p -> %p\n", buffer.buffer,
+ tegra_resource_unwrap(buffer.buffer));
+ buffer.buffer = tegra_resource_unwrap(buffer.buffer);
+ buf = &buffer;
+ }
+
+ context->gpu->set_constant_buffer(context->gpu, shader, index, buf);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_framebuffer_state(struct pipe_context *pcontext,
+ const struct pipe_framebuffer_state *fb)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_framebuffer_state state;
+ unsigned i;
+
+ debug_printf("> %s(pcontext=%p, fb=%p)\n", __func__, pcontext, fb);
+
+ if (fb) {
+ memcpy(&state, fb, sizeof(state));
+
+ for (i = 0; i < fb->nr_cbufs; i++) {
+ state.cbufs[i] = tegra_surface_unwrap(fb->cbufs[i]);
+ debug_printf(" %u: %p -> %p\n", i, fb->cbufs[i],
+ state.cbufs[i]);
+ }
+
+ while (i < PIPE_MAX_COLOR_BUFS)
+ state.cbufs[i++] = NULL;
+
+ state.zsbuf = tegra_surface_unwrap(fb->zsbuf);
+ debug_printf(" zsbuf: %p -> %p\n", fb->zsbuf, state.zsbuf);
+
+ fb = &state;
+ }
+
+ context->gpu->set_framebuffer_state(context->gpu, fb);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_polygon_stipple(struct pipe_context *pcontext,
+ const struct pipe_poly_stipple *stipple)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, stipple=%p)\n", __func__, pcontext,
+ stipple);
+
+ context->gpu->set_polygon_stipple(context->gpu, stipple);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_scissor_states(struct pipe_context *pcontext,
+ unsigned start_slot,
+ unsigned num_scissors,
+ const struct pipe_scissor_state *scissors)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, start_slot=%u, num_scissors=%u, scissors=%p)\n",
+ __func__, pcontext, start_slot, num_scissors, scissors);
+
+ context->gpu->set_scissor_states(context->gpu, start_slot,
+ num_scissors, scissors);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_viewport_states(struct pipe_context *pcontext,
+ unsigned start_slot,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, start_slot=%u, num_viewports=%u, viewports=%p)\n",
+ __func__, pcontext, start_slot, num_viewports,
+ viewports);
+
+ context->gpu->set_viewport_states(context->gpu, start_slot,
+ num_viewports, viewports);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_sampler_views(struct pipe_context *pcontext,
+ unsigned shader,
+ unsigned start_slot,
+ unsigned num_views,
+ struct pipe_sampler_view **pviews)
+{
+ struct pipe_sampler_view *views[PIPE_MAX_SHADER_SAMPLER_VIEWS];
+ struct tegra_context *context = to_tegra_context(pcontext);
+ unsigned i;
+
+ debug_printf("> %s(pcontext=%p, shader=%u, start_slot=%u, num_views=%u, pviews=%p)\n",
+ __func__, pcontext, shader, start_slot, num_views,
+ pviews);
+
+ for (i = 0; i < num_views; i++)
+ views[i] = tegra_sampler_view_unwrap(pviews[i]);
+
+ context->gpu->set_sampler_views(context->gpu, shader, start_slot,
+ num_views, views);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_shader_resources(struct pipe_context *pcontext,
+ unsigned start,
+ unsigned count,
+ struct pipe_surface **resources)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, startt=%u, count=%u, resources=%p)\n",
+ __func__, pcontext, start, count, resources);
+
+ context->gpu->set_shader_resources(context->gpu, start, count,
+ resources);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_vertex_buffers(struct pipe_context *pcontext,
+ unsigned start_slot,
+ unsigned num_buffers,
+ const struct pipe_vertex_buffer *buffers)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_vertex_buffer buf[PIPE_MAX_SHADER_INPUTS];
+ unsigned i;
+
+ debug_printf("> %s(pcontext=%p, start_slot=%u, num_buffers=%u, buffers=%p)\n",
+ __func__, pcontext, start_slot, num_buffers, buffers);
+
+ if (num_buffers && buffers) {
+ for (i = 0; i < num_buffers; i++) {
+ debug_printf(" %u:\n", i);
+ debug_printf(" stride: %u\n", buffers[i].stride);
+ debug_printf(" offset: %u\n", buffers[i].buffer_offset);
+ debug_printf(" buffer: %p\n", buffers[i].buffer);
+ debug_printf(" user: %p\n", buffers[i].user_buffer);
+ }
+
+ memcpy(buf, buffers, num_buffers * sizeof(struct pipe_vertex_buffer));
+
+ for (i = 0; i < num_buffers; i++) {
+ debug_printf(" %u: %p -> %p\n", i, buf[i].buffer,
+ tegra_resource_unwrap(buf[i].buffer));
+ buf[i].buffer = tegra_resource_unwrap(buf[i].buffer);
+ }
+
+ buffers = buf;
+ }
+
+ context->gpu->set_vertex_buffers(context->gpu, start_slot,
+ num_buffers, buffers);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_index_buffer(struct pipe_context *pcontext,
+ const struct pipe_index_buffer *buffer)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_index_buffer buf;
+
+ debug_printf("> %s(pcontext=%p, buffer=%p)\n", __func__, pcontext,
+ buffer);
+
+ if (buffer) {
+ memcpy(&buf, buffer, sizeof(buf));
+ debug_printf(" buffer: %p -> %p\n", buf.buffer,
+ tegra_resource_unwrap(buf.buffer));
+ buf.buffer = tegra_resource_unwrap(buf.buffer);
+ buffer = &buf;
+ }
+
+ context->gpu->set_index_buffer(context->gpu, buffer);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static struct pipe_stream_output_target *
+tegra_create_stream_output_target(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ unsigned buffer_offset,
+ unsigned buffer_size)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_stream_output_target *target;
+
+ debug_printf("> %s(pcontext=%p, presource=%p, buffer_offset=%u, buffer_size=%u)\n",
+ __func__, pcontext, presource, buffer_offset,
+ buffer_size);
+
+ target = context->gpu->create_stream_output_target(context->gpu,
+ resource->gpu,
+ buffer_offset,
+ buffer_size);
+
+ debug_printf("< %s() = %p\n", __func__, target);
+ return target;
+}
+
+static void
+tegra_stream_output_target_destroy(struct pipe_context *pcontext,
+ struct pipe_stream_output_target *target)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, target=%p)\n", __func__, pcontext,
+ target);
+
+ context->gpu->stream_output_target_destroy(context->gpu, target);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_set_stream_output_targets(struct pipe_context *pcontext,
+ unsigned num_targets,
+ struct pipe_stream_output_target **targets,
+ const unsigned *offsets)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, num_targets=%u, targets=%p, offsets=%p)\n",
+ __func__, pcontext, num_targets, targets, offsets);
+
+ context->gpu->set_stream_output_targets(context->gpu, num_targets,
+ targets, offsets);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_blit(struct pipe_context *pcontext,
+ const struct pipe_blit_info *pinfo)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct pipe_blit_info info;
+
+ debug_printf("> %s(pcontext=%p, pinfo=%p)\n", __func__, pcontext,
+ pinfo);
+
+ if (pinfo) {
+ memcpy(&info, pinfo, sizeof(info));
+ info.dst.resource = tegra_resource_unwrap(info.dst.resource);
+ info.src.resource = tegra_resource_unwrap(info.src.resource);
+ pinfo = &info;
+ }
+
+ context->gpu->blit(context->gpu, pinfo);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_clear(struct pipe_context *pcontext,
+ unsigned buffers,
+ const union pipe_color_union *color,
+ double depth,
+ unsigned stencil)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, buffers=%x, color=%p, depth=%f, stencil=%u)\n",
+ __func__, pcontext, buffers, color, depth, stencil);
+
+ context->gpu->clear(context->gpu, buffers, color, depth, stencil);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_flush(struct pipe_context *pcontext,
+ struct pipe_fence_handle **fence,
+ unsigned flags)
+{
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, fence=%p, flags=%x)\n", __func__,
+ pcontext, fence, flags);
+
+ context->gpu->flush(context->gpu, fence, flags);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static struct pipe_sampler_view *
+tegra_create_sampler_view(struct pipe_context *pcontext,
+ struct pipe_resource *ptexture,
+ const struct pipe_sampler_view *template)
+{
+ struct tegra_resource *texture = to_tegra_resource(ptexture);
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct tegra_sampler_view *view;
+
+ debug_printf("> %s(pcontext=%p, ptexture=%p, template=%p)\n",
+ __func__, pcontext, ptexture, template);
+
+ view = calloc(1, sizeof(*view));
+ if (!view)
+ return NULL;
+
+ view->gpu = context->gpu->create_sampler_view(context->gpu,
+ texture->gpu,
+ template);
+ memcpy(&view->base, view->gpu, sizeof(*view->gpu));
+ /* overwrite to prevent reference from being released */
+ view->base.texture = NULL;
+
+ pipe_reference_init(&view->base.reference, 1);
+ pipe_resource_reference(&view->base.texture, ptexture);
+ view->base.context = pcontext;
+
+ debug_printf("< %s() = %p\n", __func__, &view->base);
+ return &view->base;
+}
+
+static void
+tegra_sampler_view_destroy(struct pipe_context *pcontext,
+ struct pipe_sampler_view *pview)
+{
+ struct tegra_sampler_view *view = to_tegra_sampler_view(pview);
+
+ debug_printf("> %s(pcontext=%p, view=%p)\n", __func__, pcontext,
+ view);
+
+ pipe_resource_reference(&view->base.texture, NULL);
+ pipe_sampler_view_reference(&view->gpu, NULL);
+ free(view);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_flush_resource(struct pipe_context *pcontext,
+ struct pipe_resource *presource)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, presource=%p)\n", __func__, pcontext,
+ presource);
+
+ context->gpu->flush_resource(context->gpu, resource->gpu);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void *
+tegra_transfer_map(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box,
+ struct pipe_transfer **ptransfer)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct tegra_transfer *transfer;
+
+ debug_printf("> %s(pcontext=%p, presource=%p, level=%u, usage=%x, box=%p, ptransfer=%p)\n",
+ __func__, pcontext, presource, level, usage, box,
+ ptransfer);
+
+ transfer = calloc(1, sizeof(*transfer));
+ if (!transfer)
+ return NULL;
+
+ transfer->map = context->gpu->transfer_map(context->gpu,
+ resource->gpu,
+ level,
+ usage,
+ box,
+ &transfer->gpu);
+ memcpy(&transfer->base, transfer->gpu, sizeof(*transfer->gpu));
+ if (transfer->base.resource != NULL)
+ debug_printf(" resource: %p\n", transfer->base.resource);
+ transfer->base.resource = NULL;
+ pipe_resource_reference(&transfer->base.resource, presource);
+
+ *ptransfer = &transfer->base;
+
+ debug_printf("< %s() = %p\n", __func__, transfer->map);
+ return transfer->map;
+}
+
+static void
+tegra_transfer_unmap(struct pipe_context *pcontext,
+ struct pipe_transfer *ptransfer)
+{
+ struct tegra_transfer *transfer = to_tegra_transfer(ptransfer);
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, ptransfer=%p)\n", __func__, pcontext,
+ ptransfer);
+
+ context->gpu->transfer_unmap(context->gpu, transfer->gpu);
+ pipe_resource_reference(&transfer->base.resource, NULL);
+ free(transfer);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static void
+tegra_transfer_inline_write(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ unsigned level,
+ unsigned usage,
+ const struct pipe_box *box,
+ const void *data,
+ unsigned stride,
+ unsigned layer_stride)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_context *context = to_tegra_context(pcontext);
+
+ debug_printf("> %s(pcontext=%p, presource=%p, level=%u, usage=%x, box=%p, data=%p, stride=%u, layer_stride=%u)\n",
+ __func__, pcontext, presource, level, usage, box, data,
+ stride, layer_stride);
+
+ context->gpu->transfer_inline_write(context->gpu, resource->gpu,
+ level, usage, box, data, stride,
+ layer_stride);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+struct pipe_context *
+tegra_context_create(struct pipe_screen *pscreen, void *priv)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ struct tegra_context *context;
+
+ debug_printf("> %s(pscreen=%p, priv=%p)\n", __func__, pscreen, priv);
+
+ context = calloc(1, sizeof(*context));
+ if (!context)
+ return NULL;
+
+ context->gpu = screen->gpu->context_create(screen->gpu, priv);
+ if (!context->gpu) {
+ debug_error("failed to create GPU context\n");
+ free(context);
+ return NULL;
+ }
+
+ context->base.screen = &screen->base;
+ context->base.priv = priv;
+
+ context->base.destroy = tegra_destroy;
+
+ context->base.draw_vbo = tegra_draw_vbo;
+
+ context->base.create_blend_state = tegra_create_blend_state;
+ context->base.bind_blend_state = tegra_bind_blend_state;
+ context->base.delete_blend_state = tegra_delete_blend_state;
+
+ context->base.create_sampler_state = tegra_create_sampler_state;
+ context->base.bind_sampler_states = tegra_bind_sampler_states;
+ context->base.delete_sampler_state = tegra_delete_sampler_state;
+
+ context->base.create_rasterizer_state = tegra_create_rasterizer_state;
+ context->base.bind_rasterizer_state = tegra_bind_rasterizer_state;
+ context->base.delete_rasterizer_state = tegra_delete_rasterizer_state;
+
+ context->base.create_depth_stencil_alpha_state = tegra_create_depth_stencil_alpha_state;
+ context->base.bind_depth_stencil_alpha_state = tegra_bind_depth_stencil_alpha_state;
+ context->base.delete_depth_stencil_alpha_state = tegra_delete_depth_stencil_alpha_state;
+
+ context->base.create_fs_state = tegra_create_fs_state;
+ context->base.bind_fs_state = tegra_bind_fs_state;
+ context->base.delete_fs_state = tegra_delete_fs_state;
+
+ context->base.create_vs_state = tegra_create_vs_state;
+ context->base.bind_vs_state = tegra_bind_vs_state;
+ context->base.delete_vs_state = tegra_delete_vs_state;
+
+ context->base.create_gs_state = tegra_create_gs_state;
+ context->base.bind_gs_state = tegra_bind_gs_state;
+ context->base.delete_gs_state = tegra_delete_gs_state;
+
+ context->base.create_vertex_elements_state = tegra_create_vertex_elements_state;
+ context->base.bind_vertex_elements_state = tegra_bind_vertex_elements_state;
+ context->base.delete_vertex_elements_state = tegra_delete_vertex_elements_state;
+
+ context->base.set_constant_buffer = tegra_set_constant_buffer;
+ context->base.set_framebuffer_state = tegra_set_framebuffer_state;
+ context->base.set_polygon_stipple = tegra_set_polygon_stipple;
+ context->base.set_scissor_states = tegra_set_scissor_states;
+ context->base.set_viewport_states = tegra_set_viewport_states;
+ context->base.set_sampler_views = tegra_set_sampler_views;
+
+ context->base.set_shader_resources = tegra_set_shader_resources;
+ context->base.set_vertex_buffers = tegra_set_vertex_buffers;
+ context->base.set_index_buffer = tegra_set_index_buffer;
+
+ context->base.create_stream_output_target = tegra_create_stream_output_target;
+ context->base.stream_output_target_destroy = tegra_stream_output_target_destroy;
+ context->base.set_stream_output_targets = tegra_set_stream_output_targets;
+
+ context->base.blit = tegra_blit;
+ context->base.clear = tegra_clear;
+ context->base.flush = tegra_flush;
+
+ context->base.create_sampler_view = tegra_create_sampler_view;
+ context->base.sampler_view_destroy = tegra_sampler_view_destroy;
+
+ context->base.flush_resource = tegra_flush_resource;
+
+ context->base.create_surface = tegra_create_surface;
+ context->base.surface_destroy = tegra_surface_destroy;
+
+ context->base.transfer_map = tegra_transfer_map;
+ context->base.transfer_unmap = tegra_transfer_unmap;
+ context->base.transfer_inline_write = tegra_transfer_inline_write;
+
+ debug_printf("< %s() = %p\n", __func__, &context->base);
+ return &context->base;
+}
diff --git a/src/gallium/drivers/tegra/tegra_context.h b/src/gallium/drivers/tegra/tegra_context.h
new file mode 100644
index 000000000000..2a26ec6d9c63
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_context.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2014 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 TEGRA_CONTEXT_H
+#define TEGRA_CONTEXT_H
+
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+
+struct tegra_screen;
+
+struct tegra_context {
+ struct pipe_context base;
+ struct pipe_context *gpu;
+};
+
+static inline struct tegra_context *
+to_tegra_context(struct pipe_context *context)
+{
+ return (struct tegra_context *)context;
+}
+
+struct pipe_context *tegra_context_create(struct pipe_screen *pscreen,
+ void *priv);
+
+struct tegra_sampler_view {
+ struct pipe_sampler_view base;
+ struct pipe_sampler_view *gpu;
+};
+
+static INLINE struct tegra_sampler_view *
+to_tegra_sampler_view(struct pipe_sampler_view *view)
+{
+ return (struct tegra_sampler_view *)view;
+}
+
+static INLINE struct pipe_sampler_view *
+tegra_sampler_view_unwrap(struct pipe_sampler_view *view)
+{
+ if (!view)
+ return NULL;
+
+ return to_tegra_sampler_view(view)->gpu;
+}
+
+struct tegra_transfer {
+ struct pipe_transfer base;
+ struct pipe_transfer *gpu;
+
+ unsigned int count;
+ void *map;
+};
+
+static INLINE struct tegra_transfer *
+to_tegra_transfer(struct pipe_transfer *transfer)
+{
+ return (struct tegra_transfer *)transfer;
+}
+
+#endif /* TEGRA_SCREEN_H */
diff --git a/src/gallium/drivers/tegra/tegra_resource.c b/src/gallium/drivers/tegra/tegra_resource.c
new file mode 100644
index 000000000000..3b8accad9f3d
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_resource.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <drm/tegra_drm.h>
+#include <xf86drm.h>
+
+#include "pipe/p_state.h"
+#include "util/u_debug.h"
+#include "util/u_format.h"
+#include "util/u_inlines.h"
+
+#include "state_tracker/drm_driver.h"
+
+#include "tegra/tegra_context.h"
+#include "tegra/tegra_resource.h"
+#include "tegra/tegra_screen.h"
+
+struct pipe_resource *
+tegra_resource_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *template)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ struct tegra_resource *resource;
+
+ debug_printf("> %s(pscreen=%p, template=%p)\n", __func__, pscreen,
+ template);
+ /*
+ debug_printf(" template: %p\n", template);
+ debug_printf(" target: %u\n", template->target);
+ debug_printf(" format: %u\n", template->format);
+ debug_printf(" width: %u\n", template->width0);
+ debug_printf(" height: %u\n", template->height0);
+ debug_printf(" depth: %u\n", template->depth0);
+ debug_printf(" array_size: %u\n", template->array_size);
+ debug_printf(" last_level: %u\n", template->last_level);
+ debug_printf(" nr_samples: %u\n", template->nr_samples);
+ debug_printf(" usage: %u\n", template->usage);
+ debug_printf(" bind: %x\n", template->bind);
+ debug_printf(" flags: %x\n", template->flags);
+ */
+
+ resource = calloc(1, sizeof(*resource));
+ if (!resource)
+ return NULL;
+
+ /* import scanout buffers for display */
+ if (template->bind & PIPE_BIND_SCANOUT) {
+ struct drm_tegra_gem_set_tiling args;
+ struct winsys_handle handle;
+ boolean status;
+ int fd, err;
+
+ resource->gpu = screen->gpu->resource_create(screen->gpu,
+ template);
+ if (!resource->gpu)
+ goto free;
+
+ memset(&handle, 0, sizeof(handle));
+ handle.type = DRM_API_HANDLE_TYPE_FD;
+
+ status = screen->gpu->resource_get_handle(screen->gpu,
+ resource->gpu,
+ &handle);
+ if (!status)
+ goto destroy;
+
+ resource->stride = handle.stride;
+ fd = handle.handle;
+
+ err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle);
+ if (err < 0) {
+ fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n",
+ strerror(errno));
+ close(fd);
+ goto destroy;
+ }
+
+ close(fd);
+
+ memset(&args, 0, sizeof(args));
+ args.handle = resource->handle;
+ args.mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
+ args.value = 4;
+
+ err = drmIoctl(screen->fd, DRM_IOCTL_TEGRA_GEM_SET_TILING,
+ &args);
+ if (err < 0) {
+ fprintf(stderr, "failed to set tiling parameters: %s\n",
+ strerror(errno));
+ goto destroy;
+ }
+ } else {
+ resource->gpu = screen->gpu->resource_create(screen->gpu,
+ template);
+ if (!resource->gpu)
+ goto free;
+ }
+
+ debug_printf(" gpu: %p\n", resource->gpu);
+
+ memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
+ pipe_reference_init(&resource->base.reference, 1);
+ resource->base.screen = &screen->base;
+
+ debug_printf("< %s() = %p\n", __func__, &resource->base);
+ return &resource->base;
+
+destroy:
+ screen->gpu->resource_destroy(screen->gpu, resource->gpu);
+free:
+ free(resource);
+ return NULL;
+}
+
+struct pipe_resource *
+tegra_resource_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_resource *template,
+ struct winsys_handle *handle)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ struct tegra_resource *resource;
+
+ _debug_printf("> %s(pscreen=%p, template=%p, handle=%p)\n", __func__,
+ pscreen, template);
+
+ resource = calloc(1, sizeof(*resource));
+ if (!resource)
+ return NULL;
+
+ resource->gpu = screen->gpu->resource_from_handle(screen->gpu,
+ template,
+ handle);
+ if (!resource->gpu) {
+ free(resource);
+ return NULL;
+ }
+
+ memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
+ pipe_reference_init(&resource->base.reference, 1);
+ resource->base.screen = &screen->base;
+
+ _debug_printf("< %s() = %p\n", __func__, &resource->base);
+ return &resource->base;
+}
+
+boolean
+tegra_resource_get_handle(struct pipe_screen *pscreen,
+ struct pipe_resource *presource,
+ struct winsys_handle *handle)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ boolean ret = TRUE;
+
+ debug_printf("> %s(pscreen=%p, presource=%p, handle=%p)\n", __func__,
+ pscreen, presource, handle);
+
+ if (presource->bind & PIPE_BIND_SCANOUT) {
+ handle->handle = resource->handle;
+ handle->stride = resource->stride;
+ } else {
+ ret = screen->gpu->resource_get_handle(screen->gpu,
+ resource->gpu,
+ handle);
+ }
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+void
+tegra_resource_destroy(struct pipe_screen *pscreen,
+ struct pipe_resource *presource)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+
+ debug_printf("> %s(pscreen=%p, presource=%p)\n", __func__, pscreen,
+ presource);
+
+ pipe_resource_reference(&resource->gpu, NULL);
+ free(resource);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+struct pipe_surface *
+tegra_create_surface(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ const struct pipe_surface *template)
+{
+ struct tegra_resource *resource = to_tegra_resource(presource);
+ struct tegra_context *context = to_tegra_context(pcontext);
+ struct tegra_surface *surface;
+
+ debug_printf("> %s(pcontext=%p, presource=%p, template=%p)\n",
+ __func__, pcontext, presource, template);
+
+ surface = calloc(1, sizeof(*surface));
+ if (!surface)
+ return NULL;
+
+ surface->gpu = context->gpu->create_surface(context->gpu,
+ resource->gpu,
+ template);
+ if (!surface->gpu) {
+ free(surface);
+ return NULL;
+ }
+
+ memcpy(&surface->base, surface->gpu, sizeof(*surface->gpu));
+ /* overwrite to prevent reference from being released */
+ surface->base.texture = NULL;
+
+ pipe_reference_init(&surface->base.reference, 1);
+ pipe_resource_reference(&surface->base.texture, presource);
+ surface->base.context = &context->base;
+
+ debug_printf(" gpu: %p\n", surface->gpu);
+ debug_printf("< %s() = %p\n", __func__, &surface->base);
+ return &surface->base;
+}
+
+void
+tegra_surface_destroy(struct pipe_context *pcontext,
+ struct pipe_surface *psurface)
+{
+ struct tegra_surface *surface = to_tegra_surface(psurface);
+
+ debug_printf("> %s(pcontext=%p, psurface=%p)\n", __func__, pcontext,
+ psurface);
+
+ pipe_resource_reference(&surface->base.texture, NULL);
+ pipe_surface_reference(&surface->gpu, NULL);
+ free(surface);
+
+ debug_printf("< %s()\n", __func__);
+}
diff --git a/src/gallium/drivers/tegra/tegra_resource.h b/src/gallium/drivers/tegra/tegra_resource.h
new file mode 100644
index 000000000000..783fb37ec466
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_resource.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2014 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 TEGRA_RESOURCE_H
+#define TEGRA_RESOURCE_H
+
+#include "pipe/p_state.h"
+
+struct winsys_handle;
+
+struct tegra_resource {
+ struct pipe_resource base;
+ struct pipe_resource *gpu;
+
+ uint32_t stride;
+ uint32_t handle;
+ size_t size;
+};
+
+static INLINE struct tegra_resource *
+to_tegra_resource(struct pipe_resource *resource)
+{
+ return (struct tegra_resource *)resource;
+}
+
+static INLINE struct pipe_resource *
+tegra_resource_unwrap(struct pipe_resource *resource)
+{
+ if (!resource)
+ return NULL;
+
+ return to_tegra_resource(resource)->gpu;
+}
+
+struct pipe_resource *
+tegra_resource_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *template);
+struct pipe_resource *
+tegra_resource_from_handle(struct pipe_screen *pscreen,
+ const struct pipe_resource *template,
+ struct winsys_handle *handle);
+boolean
+tegra_resource_get_handle(struct pipe_screen *pscreen,
+ struct pipe_resource *resource,
+ struct winsys_handle *handle);
+void
+tegra_resource_destroy(struct pipe_screen *pscreen,
+ struct pipe_resource *resource);
+
+struct tegra_surface {
+ struct pipe_surface base;
+ struct pipe_surface *gpu;
+};
+
+static INLINE struct tegra_surface *
+to_tegra_surface(struct pipe_surface *surface)
+{
+ return (struct tegra_surface *)surface;
+}
+
+static INLINE struct pipe_surface *
+tegra_surface_unwrap(struct pipe_surface *surface)
+{
+ if (!surface)
+ return NULL;
+
+ return to_tegra_surface(surface)->gpu;
+}
+
+struct pipe_surface *
+tegra_create_surface(struct pipe_context *pcontext,
+ struct pipe_resource *presource,
+ const struct pipe_surface *template);
+void
+tegra_surface_destroy(struct pipe_context *pcontext,
+ struct pipe_surface *psurface);
+
+#endif /* TEGRA_RESOURCE_H */
diff --git a/src/gallium/drivers/tegra/tegra_screen.c b/src/gallium/drivers/tegra/tegra_screen.c
new file mode 100644
index 000000000000..b6394faa0c61
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_screen.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
+
+#include "util/u_debug.h"
+
+#include "tegra/tegra_context.h"
+#include "tegra/tegra_resource.h"
+#include "tegra/tegra_screen.h"
+
+/* TODO: obtain from include file */
+struct pipe_screen *nouveau_drm_screen_create(int fd);
+
+static const char *
+tegra_get_name(struct pipe_screen *pscreen)
+{
+ return "tegra";
+}
+
+static const char *
+tegra_get_vendor(struct pipe_screen *pscreen)
+{
+ return "tegra";
+}
+
+static void tegra_screen_destroy(struct pipe_screen *pscreen)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+
+ debug_printf("> %s(pscreen=%p)\n", __func__, pscreen);
+
+ screen->gpu->destroy(screen->gpu);
+ free(pscreen);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static int
+tegra_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ int ret;
+
+ debug_printf("> %s(pscreen=%p, param=%d)\n", __func__, pscreen,
+ param);
+
+ ret = screen->gpu->get_param(screen->gpu, param);
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static float
+tegra_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ float ret;
+
+ debug_printf("> %s(pscreen=%p, param=%d)\n", __func__, pscreen,
+ param);
+
+ ret = screen->gpu->get_paramf(screen->gpu, param);
+
+ debug_printf("< %s() = %f\n", __func__, ret);
+ return ret;
+}
+
+static int
+tegra_screen_get_shader_param(struct pipe_screen *pscreen,
+ unsigned shader,
+ enum pipe_shader_cap param)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ int ret;
+
+ debug_printf("> %s(pscreen=%p, param=%d)\n", __func__, pscreen,
+ param);
+
+ ret = screen->gpu->get_shader_param(screen->gpu, shader, param);
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static boolean
+tegra_screen_is_format_supported(struct pipe_screen *pscreen,
+ enum pipe_format format,
+ enum pipe_texture_target target,
+ unsigned sample_count,
+ unsigned usage)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ boolean ret;
+
+ debug_printf("> %s(pscreen=%p, format=%d, target=%d, sample_count=%u, usage=%x)\n",
+ __func__, pscreen, format, target, sample_count, usage);
+
+ ret = screen->gpu->is_format_supported(screen->gpu, format, target,
+ sample_count, usage);
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static void
+tegra_fence_reference(struct pipe_screen *pscreen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *fence)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+
+ debug_printf("> %s(pscreen=%p, ptr=%p, fence=%p)\n", __func__,
+ pscreen, ptr, fence);
+
+ screen->gpu->fence_reference(screen->gpu, ptr, fence);
+
+ debug_printf("< %s()\n", __func__);
+}
+
+static boolean
+tegra_fence_signalled(struct pipe_screen *pscreen,
+ struct pipe_fence_handle *fence)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ boolean ret;
+
+ debug_printf("> %s(pscreen=%p, fence=%p)\n", __func__, pscreen,
+ fence);
+
+ ret = screen->gpu->fence_signalled(screen->gpu, fence);
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static boolean
+tegra_fence_finish(struct pipe_screen *pscreen,
+ struct pipe_fence_handle *fence,
+ uint64_t timeout)
+{
+ struct tegra_screen *screen = to_tegra_screen(pscreen);
+ boolean ret;
+
+ debug_printf("> %s(pscreen=%p, fence=%p, timeout=%llu)\n", __func__,
+ pscreen, fence, timeout);
+
+ ret = screen->gpu->fence_finish(screen->gpu, fence, timeout);
+
+ debug_printf("< %s() = %d\n", __func__, ret);
+ return ret;
+}
+
+static struct udev_device *udev_device_new_from_fd(struct udev *udev, int fd)
+{
+ struct udev_device *device;
+ struct stat stat;
+ int err;
+
+ err = fstat(fd, &stat);
+ if (err < 0) {
+ fprintf(stderr, "fstat() failed: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ device = udev_device_new_from_devnum(udev, 'c', stat.st_rdev);
+ if (!device) {
+ fprintf(stderr, "udev_device_new_from_devnum() failed\n");
+ return NULL;
+ }
+
+ return device;
+}
+
+static struct udev_device *udev_device_get_root(struct udev_device *device)
+{
+ struct udev_device *parent;
+
+ debug_printf("> %s(device=%p)\n", __func__, device);
+ debug_printf(" syspath: %s\n", udev_device_get_syspath(device));
+
+ while (true) {
+ parent = udev_device_get_parent(device);
+ if (!parent)
+ break;
+
+ debug_printf(" parent: %p\n", parent);
+ debug_printf(" syspath: %s\n", udev_device_get_syspath(parent));
+ device = parent;
+ }
+
+ debug_printf("< %s() = %p\n", __func__, device);
+ return device;
+}
+
+static bool udev_device_match(struct udev_device *x, struct udev_device *y)
+{
+ const char *p1 = udev_device_get_syspath(x);
+ const char *p2 = udev_device_get_syspath(y);
+
+ return strcmp(p1, p2) == 0;
+}
+
+static int tegra_open_render_node(int fd)
+{
+ struct udev_device *display, *parent, *root;
+ struct udev_list_entry *list, *entry;
+ struct udev_enumerate *enumerate;
+ struct udev *udev;
+
+ udev = udev_new();
+ if (!udev)
+ return -ENOMEM;
+
+ display = udev_device_new_from_fd(udev, fd);
+ if (!display) {
+ udev_unref(udev);
+ return -ENODEV;
+ }
+
+ debug_printf("path: %s\n", udev_device_get_devpath(display));
+
+ parent = udev_device_get_parent(display);
+ if (!parent) {
+ udev_device_unref(display);
+ udev_unref(udev);
+ return -ENODEV;
+ }
+
+ debug_printf("parent: %s\n", udev_device_get_syspath(parent));
+
+ display = parent;
+
+ root = udev_device_get_root(display);
+ if (!root) {
+ udev_device_unref(display);
+ udev_unref(udev);
+ return -ENODEV;
+ }
+
+ debug_printf("root: %s\n", udev_device_get_syspath(root));
+
+ enumerate = udev_enumerate_new(udev);
+ if (!enumerate) {
+ udev_device_unref(display);
+ udev_unref(udev);
+ return -ENOMEM;
+ }
+
+ udev_enumerate_add_match_subsystem(enumerate, "drm");
+ udev_enumerate_add_match_sysname(enumerate, "render*");
+ udev_enumerate_scan_devices(enumerate);
+
+ list = udev_enumerate_get_list_entry(enumerate);
+
+ debug_printf("devices:\n");
+
+ udev_list_entry_foreach(entry, list) {
+ const char *path = udev_list_entry_get_name(entry);
+ struct udev_device *device, *bus;
+
+ device = udev_device_new_from_syspath(udev, path);
+ if (!device)
+ continue;
+
+ path = udev_device_get_devnode(device);
+
+ parent = udev_device_get_parent(device);
+ if (!parent) {
+ udev_device_unref(device);
+ continue;
+ }
+
+ /* do not match if the render nodes shares the same parent */
+ if (udev_device_match(parent, display)) {
+ udev_device_unref(parent);
+ udev_device_unref(device);
+ continue;
+ }
+
+ bus = udev_device_get_root(device);
+ if (!bus) {
+ udev_device_unref(parent);
+ udev_device_unref(device);
+ continue;
+ }
+
+ /* both devices need to be on the same bus, though */
+ if (udev_device_match(bus, root)) {
+ debug_printf("match found: %s\n", path);
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ fd = -errno;
+
+ break;
+ }
+ }
+
+ udev_enumerate_unref(enumerate);
+ udev_unref(udev);
+
+ return open("/dev/dri/renderD128", O_RDWR);
+}
+
+struct pipe_screen *
+tegra_screen_create(int fd)
+{
+ struct tegra_screen *screen;
+
+ debug_printf("> %s()\n", __func__);
+
+ screen = calloc(1, sizeof(*screen));
+ if (!screen)
+ return NULL;
+
+ screen->fd = fd;
+
+ screen->gpu_fd = tegra_open_render_node(screen->fd);
+ if (screen->gpu_fd < 0) {
+ fprintf(stderr, "failed to open GPU device: %s\n",
+ strerror(errno));
+ free(screen);
+ return NULL;
+ }
+
+ screen->gpu = nouveau_drm_screen_create(screen->gpu_fd);
+ if (!screen->gpu) {
+ fprintf(stderr, "failed to create GPU screen\n");
+ close(screen->gpu_fd);
+ free(screen);
+ return NULL;
+ }
+
+ debug_printf("GPU: %p\n", screen->gpu);
+ debug_printf(" fd: %d\n", screen->gpu_fd);
+
+ screen->base.get_name = tegra_get_name;
+ screen->base.get_vendor = tegra_get_vendor;
+ screen->base.destroy = tegra_screen_destroy;
+ screen->base.get_param = tegra_screen_get_param;
+ screen->base.get_paramf = tegra_screen_get_paramf;
+ screen->base.get_shader_param = tegra_screen_get_shader_param;
+ screen->base.context_create = tegra_context_create;
+ screen->base.is_format_supported = tegra_screen_is_format_supported;
+
+ screen->base.resource_create = tegra_resource_create;
+ screen->base.resource_from_handle = tegra_resource_from_handle;
+ screen->base.resource_get_handle = tegra_resource_get_handle;
+ screen->base.resource_destroy = tegra_resource_destroy;
+
+ screen->base.fence_reference = tegra_fence_reference;
+ screen->base.fence_signalled = tegra_fence_signalled;
+ screen->base.fence_finish = tegra_fence_finish;
+
+ debug_printf("< %s() = %p\n", __func__, &screen->base);
+ return &screen->base;
+}
diff --git a/src/gallium/drivers/tegra/tegra_screen.h b/src/gallium/drivers/tegra/tegra_screen.h
new file mode 100644
index 000000000000..1fba510c241f
--- /dev/null
+++ b/src/gallium/drivers/tegra/tegra_screen.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2014 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 TEGRA_SCREEN_H
+#define TEGRA_SCREEN_H
+
+#include "pipe/p_screen.h"
+
+struct tegra_screen {
+ struct pipe_screen base;
+ int fd;
+
+ struct pipe_screen *gpu;
+ int gpu_fd;
+};
+
+static inline struct tegra_screen *
+to_tegra_screen(struct pipe_screen *pscreen)
+{
+ return (struct tegra_screen *)pscreen;
+}
+
+struct pipe_screen *tegra_screen_create(int fd);
+
+#endif /* TEGRA_SCREEN_H */
diff --git a/src/gallium/targets/dri/Makefile.am b/src/gallium/targets/dri/Makefile.am
index f42dd25a56be..235eafdf66ab 100644
--- a/src/gallium/targets/dri/Makefile.am
+++ b/src/gallium/targets/dri/Makefile.am
@@ -80,6 +80,8 @@ include $(top_srcdir)/src/gallium/drivers/svga/Automake.inc
include $(top_srcdir)/src/gallium/drivers/freedreno/Automake.inc
+include $(top_srcdir)/src/gallium/drivers/tegra/Automake.inc
+
include $(top_srcdir)/src/gallium/drivers/vc4/Automake.inc
include $(top_srcdir)/src/gallium/drivers/virgl/Automake.inc
diff --git a/src/gallium/targets/dri/target.c b/src/gallium/targets/dri/target.c
index 01532e242b8d..2db3f0a4438f 100644
--- a/src/gallium/targets/dri/target.c
+++ b/src/gallium/targets/dri/target.c
@@ -161,4 +161,14 @@ PUBLIC const __DRIextension **__driDriverGetExtensions_i965(void)
return galliumdrm_driver_extensions;
}
#endif
+
+#if defined(GALLIUM_TEGRA)
+#if defined(DRI_TARGET)
+const __DRIextension **__driDriverGetExtensions_tegra(void);
+
+PUBLIC const __DRIextension **__driDriverGetExtensions_tegra(void)
+{
+ globalDriverAPI = &galliumdrm_driver_api;
+ return galliumdrm_driver_extensions;
+}
#endif
diff --git a/src/gallium/targets/pipe-loader/Makefile.am b/src/gallium/targets/pipe-loader/Makefile.am
index 18b403f73315..9635c7aaed1f 100644
--- a/src/gallium/targets/pipe-loader/Makefile.am
+++ b/src/gallium/targets/pipe-loader/Makefile.am
@@ -178,6 +178,22 @@ pipe_msm_la_LIBADD = \
endif
+if HAVE_GALLIUM_TEGRA
+pipe_LTLIBRARIES += pipe_tegra.la
+
+pipe_tegra_la_SOURCES = pipe_tegra.c
+nodist_EXTRA_pipe_tegra_la_SOURCES = dummy.cpp
+pipe_tegra_la_LIBADD = \
+ $(PIPE_LIBS) \
+ $(top_builddir)/src/gallium/winsys/tegra/drm/libtegradrm.la \
+ $(top_builddir)/src/gallium/winsys/nouveau/drm/libnouveaudrm.la \
+ $(top_builddir)/src/gallium/drivers/tegra/libtegra.la \
+ $(top_builddir)/src/gallium/drivers/nouveau/libnouveau.la \
+ $(TEGRA_LIBS) \
+ $(NOUVEAU_LIBS) \
+ $(LIBDRM_LIBS)
+endif
+
if HAVE_GALLIUM_SVGA
pipe_LTLIBRARIES += pipe_vmwgfx.la
diff --git a/src/gallium/targets/pipe-loader/pipe_tegra.c b/src/gallium/targets/pipe-loader/pipe_tegra.c
new file mode 100644
index 000000000000..ff952080ac08
--- /dev/null
+++ b/src/gallium/targets/pipe-loader/pipe_tegra.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include "state_tracker/drm_driver.h"
+#include "target-helpers/inline_debug_helper.h"
+#include "tegra/drm/tegra_drm_public.h"
+
+static struct pipe_screen *
+tegra_create_screen(int fd)
+{
+ struct pipe_screen *screen;
+
+ screen = tegra_drm_screen_create(fd);
+ if (!screen)
+ return NULL;
+
+ return debug_screen_wrap(screen);
+}
+
+PUBLIC
+DRM_DRIVER_DESCRIPTOR("tegra", "tegra", tegra_create_screen, NULL);
diff --git a/src/gallium/winsys/tegra/drm/Makefile.am b/src/gallium/winsys/tegra/drm/Makefile.am
new file mode 100644
index 000000000000..8af32530479a
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/Makefile.am
@@ -0,0 +1,11 @@
+include Makefile.sources
+include $(top_srcdir)/src/gallium/Automake.inc
+
+AM_CFLAGS = \
+ -I$(top_srcdir)/src/gallium/drivers \
+ $(GALLIUM_WINSYS_CFLAGS) \
+ $(TEGRA_CFLAGS)
+
+noinst_LTLIBRARIES = libtegradrm.la
+
+libtegradrm_la_SOURCES = $(C_SOURCES)
diff --git a/src/gallium/winsys/tegra/drm/Makefile.sources b/src/gallium/winsys/tegra/drm/Makefile.sources
new file mode 100644
index 000000000000..fe0d5c42e72d
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/Makefile.sources
@@ -0,0 +1,2 @@
+C_SOURCES := \
+ tegra_drm_winsys.c
diff --git a/src/gallium/winsys/tegra/drm/tegra_drm_public.h b/src/gallium/winsys/tegra/drm/tegra_drm_public.h
new file mode 100644
index 000000000000..45e3e006f9be
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/tegra_drm_public.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2014 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 __TEGRA_DRM_PUBLIC_H__
+#define __TEGRA_DRM_PUBLIC_H__
+
+struct pipe_screen;
+
+struct pipe_screen *tegra_drm_screen_create(int fd);
+
+#endif /* __TEGRA_DRM_PUBLIC_H__ */
diff --git a/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c b/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
new file mode 100644
index 000000000000..037a043360ab
--- /dev/null
+++ b/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2014 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.
+ */
+
+#include "util/u_debug.h"
+
+#include "tegra/tegra_screen.h"
+
+struct pipe_screen *tegra_drm_screen_create(int fd);
+
+struct pipe_screen *tegra_drm_screen_create(int fd)
+{
+ struct pipe_screen *screen;
+
+ debug_printf("> %s(fd=%d)\n", __func__, fd);
+
+ screen = tegra_screen_create(fd);
+
+ debug_printf("< %s() = %p\n", __func__, screen);
+ return screen;
+}