nouveau: Add framebuffer modifier support
authorThierry Reding <treding@nvidia.com>
Wed, 11 Oct 2017 12:38:56 +0000 (14:38 +0200)
committerThierry Reding <treding@nvidia.com>
Fri, 9 Mar 2018 10:48:08 +0000 (11:48 +0100)
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@collabora.com>
Tested-by: Andre Heider <a.heider@gmail.com>
Reviewed-by: Ilia Mirkin <imirkin@alum.mit.edu>
Signed-off-by: Thierry Reding <treding@nvidia.com>
src/gallium/drivers/nouveau/Android.mk
src/gallium/drivers/nouveau/Makefile.am
src/gallium/drivers/nouveau/meson.build
src/gallium/drivers/nouveau/nvc0/nvc0_miptree.c
src/gallium/drivers/nouveau/nvc0/nvc0_resource.c
src/gallium/drivers/nouveau/nvc0/nvc0_resource.h

index 2de22e73ec187fcde71e21fa094092f81c5c2ac5..a446774a86e8734d6de1429aaf39537352473eec 100644 (file)
@@ -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
 
index 91547178e397e2b25b5c125574bb5b325e7d2977..f6126b544811a9f2556c5d35c236f6c914cdddcd 100644 (file)
@@ -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)
index e44be2616e7043cf3eddfb787d5adb357f397ea7..242ee0e0001bf3ab8cc14fec1237b63a9df46824 100644 (file)
@@ -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],
index 27674f72a7c07936ab751e59a034528ffba9c512..7983c4030876538631e95154d4d877f9e0508912 100644 (file)
  * 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;
 
index 9bafe3d835db049bdfcd3f55d88ee9ccd7b72eed..ec6257a8963384b935492349284b81ea660c01da 100644 (file)
@@ -1,3 +1,4 @@
+#include <drm_fourcc.h>
 
 #include "pipe/p_context.h"
 #include "nvc0/nvc0_resource.h"
@@ -8,14 +9,68 @@ 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,
@@ -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;
index c68a509483600df64f1e1e69866d67e1606c171e..b24fca004cada893bd3a3e6857c4cc4095c7ea15 100644 (file)
@@ -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;