1 #include "drm-uapi/drm_fourcc.h"
2 
3 #include "pipe/p_context.h"
4 #include "nvc0/nvc0_resource.h"
5 #include "nouveau_screen.h"
6 
7 
8 static struct pipe_resource *
nvc0_resource_create(struct pipe_screen * screen,const struct pipe_resource * templ)9 nvc0_resource_create(struct pipe_screen *screen,
10                      const struct pipe_resource *templ)
11 {
12    switch (templ->target) {
13    case PIPE_BUFFER:
14       return nouveau_buffer_create(screen, templ);
15    default:
16       return nvc0_miptree_create(screen, templ, NULL, 0);
17    }
18 }
19 
20 static struct pipe_resource *
nvc0_resource_create_with_modifiers(struct pipe_screen * screen,const struct pipe_resource * templ,const uint64_t * modifiers,int count)21 nvc0_resource_create_with_modifiers(struct pipe_screen *screen,
22                                     const struct pipe_resource *templ,
23                                     const uint64_t *modifiers, int count)
24 {
25    switch (templ->target) {
26    case PIPE_BUFFER:
27       return nouveau_buffer_create(screen, templ);
28    default:
29       return nvc0_miptree_create(screen, templ, modifiers, count);
30    }
31 }
32 
33 static void
nvc0_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * res)34 nvc0_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *res)
35 {
36    if (res->target == PIPE_BUFFER)
37       nouveau_buffer_destroy(pscreen, res);
38    else
39       nv50_miptree_destroy(pscreen, res);
40 }
41 
42 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)43 nvc0_query_dmabuf_modifiers(struct pipe_screen *screen,
44                             enum pipe_format format, int max,
45                             uint64_t *modifiers, unsigned int *external_only,
46                             int *count)
47 {
48    const int s = nouveau_screen(screen)->tegra_sector_layout ? 0 : 1;
49    const uint32_t uc_kind =
50       nvc0_choose_tiled_storage_type(screen, format, 0, false);
51    const uint32_t num_uc = uc_kind ? 6 : 0; /* max block height = 32 GOBs */
52    const int num_supported = num_uc + 1; /* LINEAR is always supported */
53    const uint32_t kind_gen = nvc0_get_kind_generation(screen);
54    int i, num = 0;
55 
56    if (max > num_supported)
57       max = num_supported;
58 
59    if (!max) {
60       max = num_supported;
61       external_only = NULL;
62       modifiers = NULL;
63    }
64 
65 #define NVC0_ADD_MOD(m) do { \
66    if (modifiers) modifiers[num] = m; \
67    if (external_only) external_only[num] = 0; \
68    num++; \
69 } while (0)
70 
71    for (i = 0; i < max && i < num_uc; i++)
72       NVC0_ADD_MOD(DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, s, kind_gen,
73                                                          uc_kind, 5 - i));
74 
75    if (i < max)
76       NVC0_ADD_MOD(DRM_FORMAT_MOD_LINEAR);
77 
78 #undef NVC0_ADD_MOD
79 
80    *count = num;
81 }
82 
83 static bool
nvc0_is_dmabuf_modifier_supported(struct pipe_screen * screen,uint64_t modifier,enum pipe_format format,bool * external_only)84 nvc0_is_dmabuf_modifier_supported(struct pipe_screen *screen,
85                                   uint64_t modifier, enum pipe_format format,
86                                   bool *external_only)
87 {
88    const int s = nouveau_screen(screen)->tegra_sector_layout ? 0 : 1;
89    const uint32_t uc_kind =
90       nvc0_choose_tiled_storage_type(screen, format, 0, false);
91    const uint32_t num_uc = uc_kind ? 6 : 0; /* max block height = 32 GOBs */
92    const uint32_t kind_gen = nvc0_get_kind_generation(screen);
93    int i;
94 
95    if (modifier == DRM_FORMAT_MOD_LINEAR) {
96       if (external_only)
97          *external_only = false;
98 
99       return true;
100    }
101 
102    for (i = 0; i < num_uc; i++) {
103       if (DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, s, kind_gen, uc_kind, i) == modifier) {
104          if (external_only)
105             *external_only = false;
106 
107          return true;
108       }
109    }
110 
111    return false;
112 }
113 
114 static struct pipe_resource *
nvc0_resource_from_handle(struct pipe_screen * screen,const struct pipe_resource * templ,struct winsys_handle * whandle,unsigned usage)115 nvc0_resource_from_handle(struct pipe_screen * screen,
116                           const struct pipe_resource *templ,
117                           struct winsys_handle *whandle,
118                           unsigned usage)
119 {
120    if (templ->target == PIPE_BUFFER) {
121       return NULL;
122    } else {
123       struct pipe_resource *res = nv50_miptree_from_handle(screen,
124                                                            templ, whandle);
125       return res;
126    }
127 }
128 
129 static struct pipe_surface *
nvc0_surface_create(struct pipe_context * pipe,struct pipe_resource * pres,const struct pipe_surface * templ)130 nvc0_surface_create(struct pipe_context *pipe,
131                     struct pipe_resource *pres,
132                     const struct pipe_surface *templ)
133 {
134    if (unlikely(pres->target == PIPE_BUFFER))
135       return nv50_surface_from_buffer(pipe, pres, templ);
136    return nvc0_miptree_surface_new(pipe, pres, templ);
137 }
138 
139 static struct pipe_resource *
nvc0_resource_from_user_memory(struct pipe_screen * pipe,const struct pipe_resource * templ,void * user_memory)140 nvc0_resource_from_user_memory(struct pipe_screen *pipe,
141                                const struct pipe_resource *templ,
142                                void *user_memory)
143 {
144    ASSERTED struct nouveau_screen *screen = nouveau_screen(pipe);
145 
146    assert(screen->has_svm);
147    assert(templ->target == PIPE_BUFFER);
148 
149    return nouveau_buffer_create_from_user(pipe, templ, user_memory);
150 }
151 
152 void
nvc0_init_resource_functions(struct pipe_context * pcontext)153 nvc0_init_resource_functions(struct pipe_context *pcontext)
154 {
155    pcontext->buffer_map = nouveau_buffer_transfer_map;
156    pcontext->texture_map = nvc0_miptree_transfer_map;
157    pcontext->transfer_flush_region = nouveau_buffer_transfer_flush_region;
158    pcontext->buffer_unmap = nouveau_buffer_transfer_unmap;
159    pcontext->texture_unmap = nvc0_miptree_transfer_unmap;
160    pcontext->buffer_subdata = u_default_buffer_subdata;
161    pcontext->texture_subdata = u_default_texture_subdata;
162    pcontext->create_surface = nvc0_surface_create;
163    pcontext->surface_destroy = nv50_surface_destroy;
164    pcontext->invalidate_resource = nv50_invalidate_resource;
165 }
166 
167 void
nvc0_screen_init_resource_functions(struct pipe_screen * pscreen)168 nvc0_screen_init_resource_functions(struct pipe_screen *pscreen)
169 {
170    pscreen->resource_create = nvc0_resource_create;
171    pscreen->resource_create_with_modifiers = nvc0_resource_create_with_modifiers;
172    pscreen->query_dmabuf_modifiers = nvc0_query_dmabuf_modifiers;
173    pscreen->is_dmabuf_modifier_supported = nvc0_is_dmabuf_modifier_supported;
174    pscreen->resource_from_handle = nvc0_resource_from_handle;
175    pscreen->resource_get_handle = nvc0_miptree_get_handle;
176    pscreen->resource_destroy = nvc0_resource_destroy;
177    pscreen->resource_from_user_memory = nvc0_resource_from_user_memory;
178 }
179