Mesa (master): nouveau: Add framebuffer modifier support

Thierry Reding tagr at kemper.freedesktop.org
Fri Mar 9 10:49:35 UTC 2018


Module: Mesa
Branch: master
Commit: 2052dbdae363f4fd184842733ff9c96bd6e7f08c
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=2052dbdae363f4fd184842733ff9c96bd6e7f08c

Author: Thierry Reding <treding at nvidia.com>
Date:   Wed Oct 11 14:38:56 2017 +0200

nouveau: Add framebuffer modifier support

This adds support for framebuffer modifiers to Nouveau. This will be
used by the Tegra driver to share metadata about the format of buffers
(such as the tiling mode or compression).

Changes in v2:
- remove unused parameters to nouveau_buffer_create()
- move format modifier query code to nvc0 backend
- restrict format modifiers to 2D textures
- implement ->query_dmabuf_modifiers()

Changes in v4:
- add UAPI include path on meson builds

Changes in v5:
- remove unnecessary includes

Acked-by: Emil Velikov <emil.velikov at collabora.com>
Tested-by: Andre Heider <a.heider at gmail.com>
Reviewed-by: Ilia Mirkin <imirkin at alum.mit.edu>
Signed-off-by: Thierry Reding <treding at nvidia.com>

---

 src/gallium/drivers/nouveau/Android.mk           |  3 +
 src/gallium/drivers/nouveau/Makefile.am          |  1 +
 src/gallium/drivers/nouveau/meson.build          |  4 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c  | 81 +++++++++++++++++++++++-
 src/gallium/drivers/nouveau/nvc0/nvc0_resource.c | 59 ++++++++++++++++-
 src/gallium/drivers/nouveau/nvc0/nvc0_resource.h |  3 +-
 6 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/src/gallium/drivers/nouveau/Android.mk b/src/gallium/drivers/nouveau/Android.mk
index 2de22e73ec..a446774a86 100644
--- a/src/gallium/drivers/nouveau/Android.mk
+++ b/src/gallium/drivers/nouveau/Android.mk
@@ -36,6 +36,9 @@ LOCAL_SRC_FILES := \
 	$(NVC0_CODEGEN_SOURCES) \
 	$(NVC0_C_SOURCES)
 
+LOCAL_C_INCLUDES := \
+	$(MESA_TOP)/include/drm-uapi
+
 LOCAL_SHARED_LIBRARIES := libdrm_nouveau
 LOCAL_MODULE := libmesa_pipe_nouveau
 
diff --git a/src/gallium/drivers/nouveau/Makefile.am b/src/gallium/drivers/nouveau/Makefile.am
index 91547178e3..f6126b5448 100644
--- a/src/gallium/drivers/nouveau/Makefile.am
+++ b/src/gallium/drivers/nouveau/Makefile.am
@@ -24,6 +24,7 @@ include Makefile.sources
 include $(top_srcdir)/src/gallium/Automake.inc
 
 AM_CPPFLAGS = \
+	-I$(top_srcdir)/include/drm-uapi \
 	$(GALLIUM_DRIVER_CFLAGS) \
 	$(LIBDRM_CFLAGS) \
 	$(NOUVEAU_CFLAGS)
diff --git a/src/gallium/drivers/nouveau/meson.build b/src/gallium/drivers/nouveau/meson.build
index e44be2616e..242ee0e000 100644
--- a/src/gallium/drivers/nouveau/meson.build
+++ b/src/gallium/drivers/nouveau/meson.build
@@ -207,7 +207,9 @@ files_libnouveau = files(
 libnouveau = static_library(
   'nouveau',
   [files_libnouveau],
-  include_directories : [inc_src, inc_include, inc_gallium, inc_gallium_aux],
+  include_directories : [
+    inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_drm_uapi
+  ],
   c_args : [c_vis_args],
   cpp_args : [cpp_vis_args],
   dependencies : [dep_libdrm, dep_libdrm_nouveau],
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c b/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c
index 27674f72a7..7983c40308 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c
@@ -20,8 +20,11 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <drm_fourcc.h>
+
 #include "pipe/p_state.h"
 #include "pipe/p_defines.h"
+#include "state_tracker/drm_driver.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
 
@@ -233,9 +236,79 @@ nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
    }
 }
 
+static uint64_t nvc0_miptree_get_modifier(struct nv50_miptree *mt)
+{
+   union nouveau_bo_config *config = &mt->base.bo->config;
+   uint64_t modifier;
+
+   if (mt->layout_3d)
+      return DRM_FORMAT_MOD_INVALID;
+
+   switch (config->nvc0.memtype) {
+   case 0x00:
+      modifier = DRM_FORMAT_MOD_LINEAR;
+      break;
+
+   case 0xfe:
+      switch (NVC0_TILE_MODE_Y(config->nvc0.tile_mode)) {
+      case 0:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB;
+         break;
+
+      case 1:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB;
+         break;
+
+      case 2:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB;
+         break;
+
+      case 3:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB;
+         break;
+
+      case 4:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB;
+         break;
+
+      case 5:
+         modifier = DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB;
+         break;
+
+      default:
+         modifier = DRM_FORMAT_MOD_INVALID;
+         break;
+      }
+      break;
+
+   default:
+      modifier = DRM_FORMAT_MOD_INVALID;
+      break;
+   }
+
+   return modifier;
+}
+
+static boolean
+nvc0_miptree_get_handle(struct pipe_screen *pscreen,
+                        struct pipe_resource *pt,
+                        struct winsys_handle *whandle)
+{
+   struct nv50_miptree *mt = nv50_miptree(pt);
+   boolean ret;
+
+   ret = nv50_miptree_get_handle(pscreen, pt, whandle);
+   if (!ret)
+      return ret;
+
+   whandle->modifier = nvc0_miptree_get_modifier(mt);
+
+   return true;
+}
+
 const struct u_resource_vtbl nvc0_miptree_vtbl =
 {
-   nv50_miptree_get_handle,         /* get_handle */
+   nvc0_miptree_get_handle,         /* get_handle */
    nv50_miptree_destroy,            /* resource_destroy */
    nvc0_miptree_transfer_map,       /* transfer_map */
    u_default_transfer_flush_region, /* transfer_flush_region */
@@ -244,7 +317,8 @@ const struct u_resource_vtbl nvc0_miptree_vtbl =
 
 struct pipe_resource *
 nvc0_miptree_create(struct pipe_screen *pscreen,
-                    const struct pipe_resource *templ)
+                    const struct pipe_resource *templ,
+                    const uint64_t *modifiers, unsigned int count)
 {
    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
    struct nouveau_drm *drm = nouveau_screen(pscreen)->drm;
@@ -277,6 +351,9 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
       }
    }
 
+   if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_LINEAR)
+      pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
+
    if (pt->bind & PIPE_BIND_LINEAR)
       pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR;
 
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c
index 9bafe3d835..ec6257a896 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.c
@@ -1,3 +1,4 @@
+#include <drm_fourcc.h>
 
 #include "pipe/p_context.h"
 #include "nvc0/nvc0_resource.h"
@@ -8,15 +9,69 @@ static struct pipe_resource *
 nvc0_resource_create(struct pipe_screen *screen,
                      const struct pipe_resource *templ)
 {
+   const uint64_t modifier = DRM_FORMAT_MOD_INVALID;
+
    switch (templ->target) {
    case PIPE_BUFFER:
       return nouveau_buffer_create(screen, templ);
    default:
-      return nvc0_miptree_create(screen, templ);
+      return nvc0_miptree_create(screen, templ, &modifier, 1);
    }
 }
 
 static struct pipe_resource *
+nvc0_resource_create_with_modifiers(struct pipe_screen *screen,
+                                    const struct pipe_resource *templ,
+                                    const uint64_t *modifiers, int count)
+{
+   switch (templ->target) {
+   case PIPE_BUFFER:
+      return nouveau_buffer_create(screen, templ);
+   default:
+      return nvc0_miptree_create(screen, templ, modifiers, count);
+   }
+}
+
+static void
+nvc0_query_dmabuf_modifiers(struct pipe_screen *screen,
+                            enum pipe_format format, int max,
+                            uint64_t *modifiers, unsigned int *external_only,
+                            int *count)
+{
+   static const uint64_t supported_modifiers[] = {
+      DRM_FORMAT_MOD_LINEAR,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB,
+      DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB,
+   };
+   int i, num = 0;
+
+   if (max > ARRAY_SIZE(supported_modifiers))
+      max = ARRAY_SIZE(supported_modifiers);
+
+   if (!max) {
+      max = ARRAY_SIZE(supported_modifiers);
+      external_only = NULL;
+      modifiers = NULL;
+   }
+
+   for (i = 0; i < max; i++) {
+      if (modifiers)
+         modifiers[num] = supported_modifiers[i];
+
+      if (external_only)
+         external_only[num] = 0;
+
+      num++;
+   }
+
+   *count = num;
+}
+
+static struct pipe_resource *
 nvc0_resource_from_handle(struct pipe_screen * screen,
                           const struct pipe_resource *templ,
                           struct winsys_handle *whandle,
@@ -60,6 +115,8 @@ void
 nvc0_screen_init_resource_functions(struct pipe_screen *pscreen)
 {
    pscreen->resource_create = nvc0_resource_create;
+   pscreen->resource_create_with_modifiers = nvc0_resource_create_with_modifiers;
+   pscreen->query_dmabuf_modifiers = nvc0_query_dmabuf_modifiers;
    pscreen->resource_from_handle = nvc0_resource_from_handle;
    pscreen->resource_get_handle = u_resource_get_handle_vtbl;
    pscreen->resource_destroy = u_resource_destroy_vtbl;
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.h b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.h
index c68a509483..b24fca004c 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_resource.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_resource.h
@@ -35,7 +35,8 @@ nvc0_screen_init_resource_functions(struct pipe_screen *pscreen);
  */
 struct pipe_resource *
 nvc0_miptree_create(struct pipe_screen *pscreen,
-                    const struct pipe_resource *tmp);
+                    const struct pipe_resource *tmp,
+                    const uint64_t *modifiers, unsigned int count);
 
 const struct u_resource_vtbl nvc0_miptree_vtbl;
 




More information about the mesa-commit mailing list