On Thu, Nov 27, 2014 at 11:39 AM, Thierry Reding <thierry.red...@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 <tred...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev