[Nouveau] [Mesa-dev] [RFC] tegra: Initial support
Rob Clark
robdclark at gmail.com
Thu Nov 27 08:51:08 PST 2014
On Thu, Nov 27, 2014 at 11:39 AM, Thierry Reding
<thierry.reding at gmail.com> wrote:
> Tegra K1 and later use a GPU that can be driven by the Nouveau driver.
> But the GPU is a pure render node and has no display engine, hence the
> scanout needs to happen on the Tegra display hardware. The GPU and the
> display engine each have a separate DRM device node exposed by the
> kernel.
>
> To make the setup appear as a single device, this driver instantiates
> a Nouveau screen with each instance of a Tegra screen and forwards GPU
> requests to the Nouveau screen. For purposes of scanout it will import
> buffers created on the GPU into the display driver. Handles that
> userspace requests are those of the display driver so that they can be
> used to create framebuffers.
>
> This has been tested with some GBM test programs, as well as kmscube and
> weston. All of those run without modifications, but I'm sure there is a
> lot that can be improved.
>
> TODO:
> - use Nouveau headers to get at the prototype for creating a screen
> - implement enough support to seamlessly integrate with X
> - refactor some of the code to be reusable by other drivers
I haven't looked too carefully at the implementation yet, but couldn't
you just put in src/gallium/drivers/shim ? I guess you'd just want a
small if/else ladder where you create the *actual* screen, to create a
nouveau screen for tegra, an etnaviv screen for imx, armada, etc..?
BR,
-R
>
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
> configure.ac | 12 +-
> src/gallium/Makefile.am | 5 +
> .../auxiliary/target-helpers/inline_drm_helper.h | 30 +
> src/gallium/drivers/tegra/Automake.inc | 11 +
> src/gallium/drivers/tegra/Makefile.am | 17 +
> src/gallium/drivers/tegra/Makefile.sources | 4 +
> src/gallium/drivers/tegra/tegra_context.c | 699 +++++++++++++++++++++
> src/gallium/drivers/tegra/tegra_context.h | 80 +++
> src/gallium/drivers/tegra/tegra_resource.c | 219 +++++++
> src/gallium/drivers/tegra/tegra_resource.h | 98 +++
> src/gallium/drivers/tegra/tegra_screen.c | 311 +++++++++
> src/gallium/drivers/tegra/tegra_screen.h | 45 ++
> src/gallium/targets/dri/Makefile.am | 2 +
> src/gallium/winsys/tegra/drm/Makefile.am | 11 +
> src/gallium/winsys/tegra/drm/Makefile.sources | 2 +
> src/gallium/winsys/tegra/drm/tegra_drm_public.h | 31 +
> src/gallium/winsys/tegra/drm/tegra_drm_winsys.c | 33 +
> 17 files changed, 1609 insertions(+), 1 deletion(-)
> create mode 100644 src/gallium/drivers/tegra/Automake.inc
> create mode 100644 src/gallium/drivers/tegra/Makefile.am
> create mode 100644 src/gallium/drivers/tegra/Makefile.sources
> create mode 100644 src/gallium/drivers/tegra/tegra_context.c
> create mode 100644 src/gallium/drivers/tegra/tegra_context.h
> create mode 100644 src/gallium/drivers/tegra/tegra_resource.c
> create mode 100644 src/gallium/drivers/tegra/tegra_resource.h
> create mode 100644 src/gallium/drivers/tegra/tegra_screen.c
> create mode 100644 src/gallium/drivers/tegra/tegra_screen.h
> create mode 100644 src/gallium/winsys/tegra/drm/Makefile.am
> create mode 100644 src/gallium/winsys/tegra/drm/Makefile.sources
> create mode 100644 src/gallium/winsys/tegra/drm/tegra_drm_public.h
> create mode 100644 src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
>
> diff --git a/configure.ac b/configure.ac
> index 1d9d015481ec..ae50bec95339 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -33,6 +33,7 @@ LIBDRM_INTEL_REQUIRED=2.4.52
> LIBDRM_NVVIEUX_REQUIRED=2.4.33
> LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41"
> LIBDRM_FREEDRENO_REQUIRED=2.4.57
> +LIBDRM_TEGRA_REQUIRED=2.4.58
> DRI2PROTO_REQUIRED=2.6
> DRI3PROTO_REQUIRED=1.0
> PRESENTPROTO_REQUIRED=1.0
> @@ -733,7 +734,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"
> + "i915,ilo,nouveau,r300,r600,radeonsi,freedreno,tegra,svga,swrast,vc4"
> @<:@default=r300,r600,svga,swrast@:>@])],
> [with_gallium_drivers="$withval"],
> [with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"])
> @@ -1937,6 +1938,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
> @@ -2018,6 +2025,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_VC4, test "x$HAVE_GALLIUM_VC4" = xyes)
> @@ -2159,6 +2167,7 @@ AC_CONFIG_FILES([Makefile
> src/gallium/drivers/rbug/Makefile
> src/gallium/drivers/softpipe/Makefile
> src/gallium/drivers/svga/Makefile
> + src/gallium/drivers/tegra/Makefile
> src/gallium/drivers/trace/Makefile
> src/gallium/drivers/vc4/Makefile
> src/gallium/drivers/vc4/kernel/Makefile
> @@ -2204,6 +2213,7 @@ AC_CONFIG_FILES([Makefile
> src/gallium/winsys/sw/wayland/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/gbm/Makefile
> src/gbm/main/gbm.pc
> diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am
> index 81840b2081b6..1e76681a7329 100644
> --- a/src/gallium/Makefile.am
> +++ b/src/gallium/Makefile.am
> @@ -77,6 +77,11 @@ SUBDIRS += drivers/llvmpipe
> endif
> 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/inline_drm_helper.h b/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
> index 81649d42582c..5808765a503e 100644
> --- a/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
> +++ b/src/gallium/auxiliary/target-helpers/inline_drm_helper.h
> @@ -58,6 +58,10 @@
> #include "vc4/drm/vc4_drm_public.h"
> #endif
>
> +#if GALLIUM_TEGRA
> +#include "tegra/drm/tegra_drm_public.h"
> +#endif
> +
> static char* driver_name = NULL;
>
> /* XXX: We need to teardown the winsys if *screen_create() fails. */
> @@ -332,6 +336,27 @@ pipe_vc4_create_screen(int fd)
> }
> #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
> +
> +static 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;
> +}
> +#endif
> +
> inline struct pipe_screen *
> dd_create_screen(int fd)
> {
> @@ -389,6 +414,11 @@ dd_create_screen(int fd)
> else
> #endif
> #endif
> +#if defined(GALLIUM_TEGRA)
> + if (strcmp(driver_name, "tegra") == 0)
> + return pipe_tegra_create_screen(fd);
> + else
> +#endif
> return NULL;
> }
>
> 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..a7a7690ec7bb
> --- /dev/null
> +++ b/src/gallium/drivers/tegra/tegra_context.c
> @@ -0,0 +1,699 @@
> +/*
> + * 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);
> +
> + context->gpu->destroy(context->gpu);
> + free(context);
> +}
> +
> +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;
> +
> + if (pinfo && pinfo->indirect) {
> + memcpy(&info, pinfo, sizeof(info));
> + info.indirect = tegra_resource_unwrap(info.indirect);
> + pinfo = &info;
> + }
> +
> + context->gpu->draw_vbo(context->gpu, pinfo);
> +}
> +
> +static void *
> +tegra_create_blend_state(struct pipe_context *pcontext,
> + const struct pipe_blend_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_blend_state(context->gpu, cso);
> +}
> +
> +static void
> +tegra_bind_blend_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_blend_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_blend_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_blend_state(context->gpu, so);
> +}
> +
> +static void *
> +tegra_create_sampler_state(struct pipe_context *pcontext,
> + const struct pipe_sampler_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_sampler_state(context->gpu, cso);
> +}
> +
> +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);
> +
> + context->gpu->bind_sampler_states(context->gpu, shader, start_slot,
> + num_samplers, samplers);
> +}
> +
> +static void
> +tegra_delete_sampler_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_sampler_state(context->gpu, so);
> +}
> +
> +static void *
> +tegra_create_rasterizer_state(struct pipe_context *pcontext,
> + const struct pipe_rasterizer_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_rasterizer_state(context->gpu, cso);
> +}
> +
> +static void
> +tegra_bind_rasterizer_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_rasterizer_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_rasterizer_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_rasterizer_state(context->gpu, so);
> +}
> +
> +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);
> +
> + return context->gpu->create_depth_stencil_alpha_state(context->gpu,
> + cso);
> +}
> +
> +static void
> +tegra_bind_depth_stencil_alpha_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_depth_stencil_alpha_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_depth_stencil_alpha_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_depth_stencil_alpha_state(context->gpu, so);
> +}
> +
> +static void *
> +tegra_create_fs_state(struct pipe_context *pcontext,
> + const struct pipe_shader_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_fs_state(context->gpu, cso);
> +}
> +
> +static void
> +tegra_bind_fs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_fs_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_fs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_fs_state(context->gpu, so);
> +}
> +
> +static void *
> +tegra_create_vs_state(struct pipe_context *pcontext,
> + const struct pipe_shader_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_vs_state(context->gpu, cso);
> +}
> +
> +static void
> +tegra_bind_vs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_vs_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_vs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_vs_state(context->gpu, so);
> +}
> +
> +static void *
> +tegra_create_gs_state(struct pipe_context *pcontext,
> + const struct pipe_shader_state *cso)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + return context->gpu->create_gs_state(context->gpu, cso);
> +}
> +
> +static void
> +tegra_bind_gs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_gs_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_gs_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_gs_state(context->gpu, so);
> +}
> +
> +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);
> +
> + return context->gpu->create_vertex_elements_state(context->gpu,
> + num_elements,
> + elements);
> +}
> +
> +static void
> +tegra_bind_vertex_elements_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->bind_vertex_elements_state(context->gpu, so);
> +}
> +
> +static void
> +tegra_delete_vertex_elements_state(struct pipe_context *pcontext,
> + void *so)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->delete_vertex_elements_state(context->gpu, so);
> +}
> +
> +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;
> +
> + if (buf && buf->buffer) {
> + memcpy(&buffer, buf, sizeof(buffer));
> + buffer.buffer = tegra_resource_unwrap(buffer.buffer);
> + buf = &buffer;
> + }
> +
> + context->gpu->set_constant_buffer(context->gpu, shader, index, buf);
> +}
> +
> +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;
> +
> + if (fb) {
> + memcpy(&state, fb, sizeof(state));
> +
> + for (i = 0; i < fb->nr_cbufs; i++)
> + state.cbufs[i] = tegra_surface_unwrap(fb->cbufs[i]);
> +
> + while (i < PIPE_MAX_COLOR_BUFS)
> + state.cbufs[i++] = NULL;
> +
> + state.zsbuf = tegra_surface_unwrap(fb->zsbuf);
> +
> + fb = &state;
> + }
> +
> + context->gpu->set_framebuffer_state(context->gpu, fb);
> +}
> +
> +static void
> +tegra_set_polygon_stipple(struct pipe_context *pcontext,
> + const struct pipe_poly_stipple *stipple)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->set_polygon_stipple(context->gpu, stipple);
> +}
> +
> +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);
> +
> + context->gpu->set_scissor_states(context->gpu, start_slot,
> + num_scissors, scissors);
> +}
> +
> +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);
> +
> + context->gpu->set_viewport_states(context->gpu, start_slot,
> + num_viewports, viewports);
> +}
> +
> +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;
> +
> + 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);
> +}
> +
> +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);
> +
> + context->gpu->set_shader_resources(context->gpu, start, count,
> + resources);
> +}
> +
> +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;
> +
> + if (num_buffers && buffers) {
> + memcpy(buf, buffers, num_buffers * sizeof(struct pipe_vertex_buffer));
> +
> + for (i = 0; i < num_buffers; i++)
> + buf[i].buffer = tegra_resource_unwrap(buf[i].buffer);
> +
> + buffers = buf;
> + }
> +
> + context->gpu->set_vertex_buffers(context->gpu, start_slot,
> + num_buffers, buffers);
> +}
> +
> +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;
> +
> + if (buffer) {
> + memcpy(&buf, buffer, sizeof(buf));
> + buf.buffer = tegra_resource_unwrap(buf.buffer);
> + buffer = &buf;
> + }
> +
> + context->gpu->set_index_buffer(context->gpu, buffer);
> +}
> +
> +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);
> +
> + return context->gpu->create_stream_output_target(context->gpu,
> + resource->gpu,
> + buffer_offset,
> + buffer_size);
> +}
> +
> +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);
> +
> + context->gpu->stream_output_target_destroy(context->gpu, target);
> +}
> +
> +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);
> +
> + context->gpu->set_stream_output_targets(context->gpu, num_targets,
> + targets, offsets);
> +}
> +
> +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;
> +
> + 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);
> +}
> +
> +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);
> +
> + context->gpu->clear(context->gpu, buffers, color, depth, stencil);
> +}
> +
> +static void
> +tegra_flush(struct pipe_context *pcontext,
> + struct pipe_fence_handle **fence,
> + unsigned flags)
> +{
> + struct tegra_context *context = to_tegra_context(pcontext);
> +
> + context->gpu->flush(context->gpu, fence, flags);
> +}
> +
> +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;
> +
> + 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;
> +
> + 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);
> +
> + pipe_resource_reference(&view->base.texture, NULL);
> + pipe_sampler_view_reference(&view->gpu, NULL);
> + free(view);
> +}
> +
> +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);
> +
> + context->gpu->flush_resource(context->gpu, resource->gpu);
> +}
> +
> +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;
> +
> + 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));
> + transfer->base.resource = NULL;
> + pipe_resource_reference(&transfer->base.resource, presource);
> +
> + *ptransfer = &transfer->base;
> +
> + 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);
> +
> + context->gpu->transfer_unmap(context->gpu, transfer->gpu);
> + pipe_resource_reference(&transfer->base.resource, NULL);
> + free(transfer);
> +}
> +
> +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);
> +
> + context->gpu->transfer_inline_write(context->gpu, resource->gpu,
> + level, usage, box, data, stride,
> + layer_stride);
> +}
> +
> +struct pipe_context *
> +tegra_context_create(struct pipe_screen *pscreen, void *priv)
> +{
> + struct tegra_screen *screen = to_tegra_screen(pscreen);
> + struct tegra_context *context;
> +
> + 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;
> +
> + 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..8c5b7d4e41fc
> --- /dev/null
> +++ b/src/gallium/drivers/tegra/tegra_resource.c
> @@ -0,0 +1,219 @@
> +/*
> + * 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;
> +
> + 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;
> + }
> +
> + memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
> + pipe_reference_init(&resource->base.reference, 1);
> + resource->base.screen = &screen->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;
> +
> + 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;
> +
> + 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;
> +
> + 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);
> + }
> +
> + return ret;
> +}
> +
> +void
> +tegra_resource_destroy(struct pipe_screen *pscreen,
> + struct pipe_resource *presource)
> +{
> + struct tegra_resource *resource = to_tegra_resource(presource);
> +
> + pipe_resource_reference(&resource->gpu, NULL);
> + free(resource);
> +}
> +
> +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;
> +
> + 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;
> +
> + return &surface->base;
> +}
> +
> +void
> +tegra_surface_destroy(struct pipe_context *pcontext,
> + struct pipe_surface *psurface)
> +{
> + struct tegra_surface *surface = to_tegra_surface(psurface);
> +
> + pipe_resource_reference(&surface->base.texture, NULL);
> + pipe_surface_reference(&surface->gpu, NULL);
> + free(surface);
> +}
> 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..aa7bf65cb7ec
> --- /dev/null
> +++ b/src/gallium/drivers/tegra/tegra_screen.c
> @@ -0,0 +1,311 @@
> +/*
> + * 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);
> +
> + screen->gpu->destroy(screen->gpu);
> + free(pscreen);
> +}
> +
> +static int
> +tegra_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
> +{
> + struct tegra_screen *screen = to_tegra_screen(pscreen);
> +
> + return screen->gpu->get_param(screen->gpu, param);
> +}
> +
> +static float
> +tegra_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
> +{
> + struct tegra_screen *screen = to_tegra_screen(pscreen);
> +
> + return screen->gpu->get_paramf(screen->gpu, param);
> +}
> +
> +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);
> +
> + return screen->gpu->get_shader_param(screen->gpu, shader, param);
> +}
> +
> +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);
> +
> + return screen->gpu->is_format_supported(screen->gpu, format, target,
> + sample_count, usage);
> +}
> +
> +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);
> +
> + screen->gpu->fence_reference(screen->gpu, ptr, fence);
> +}
> +
> +static boolean
> +tegra_fence_signalled(struct pipe_screen *pscreen,
> + struct pipe_fence_handle *fence)
> +{
> + struct tegra_screen *screen = to_tegra_screen(pscreen);
> +
> + return screen->gpu->fence_signalled(screen->gpu, fence);
> +}
> +
> +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);
> +
> + return screen->gpu->fence_finish(screen->gpu, fence, timeout);
> +}
> +
> +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;
> +
> + while (true) {
> + parent = udev_device_get_parent(device);
> + if (!parent)
> + break;
> +
> + device = parent;
> + }
> +
> + 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;
> + }
> +
> + parent = udev_device_get_parent(display);
> + if (!parent) {
> + udev_device_unref(display);
> + udev_unref(udev);
> + return -ENODEV;
> + }
> +
> + display = parent;
> +
> + root = udev_device_get_root(display);
> + if (!root) {
> + udev_device_unref(display);
> + udev_unref(udev);
> + return -ENODEV;
> + }
> +
> + 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);
> +
> + 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)) {
> + 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;
> +
> + 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;
> + }
> +
> + 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;
> +
> + 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 3c7140d75b5c..0406eaf66537 100644
> --- a/src/gallium/targets/dri/Makefile.am
> +++ b/src/gallium/targets/dri/Makefile.am
> @@ -83,6 +83,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/softpipe/Automake.inc
> diff --git a/src/gallium/winsys/tegra/drm/Makefile.am b/src/gallium/winsys/tegra/drm/Makefile.am
> new file mode 100644
> index 000000000000..8e3685ee20e8
> --- /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) \
> + $(FREEDRENO_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..99b0e1649026
> --- /dev/null
> +++ b/src/gallium/winsys/tegra/drm/tegra_drm_winsys.c
> @@ -0,0 +1,33 @@
> +/*
> + * 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)
> +{
> + return tegra_screen_create(fd);
> +}
> --
> 2.1.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the Nouveau
mailing list