• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014-2018 NVIDIA Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <inttypes.h>
27 #include <stdio.h>
28 
29 #include <sys/stat.h>
30 
31 #include "drm-uapi/drm_fourcc.h"
32 #include "drm-uapi/tegra_drm.h"
33 #include <xf86drm.h>
34 
35 #include "loader/loader.h"
36 #include "pipe/p_state.h"
37 #include "util/u_debug.h"
38 #include "util/u_inlines.h"
39 
40 #include "frontend/drm_driver.h"
41 
42 #include "nouveau/drm/nouveau_drm_public.h"
43 
44 #include "tegra_context.h"
45 #include "tegra_resource.h"
46 #include "tegra_screen.h"
47 
tegra_screen_destroy(struct pipe_screen * pscreen)48 static void tegra_screen_destroy(struct pipe_screen *pscreen)
49 {
50    struct tegra_screen *screen = to_tegra_screen(pscreen);
51 
52    screen->gpu->destroy(screen->gpu);
53    free(pscreen);
54 }
55 
56 static const char *
tegra_screen_get_name(struct pipe_screen * pscreen)57 tegra_screen_get_name(struct pipe_screen *pscreen)
58 {
59    return "tegra";
60 }
61 
62 static const char *
tegra_screen_get_vendor(struct pipe_screen * pscreen)63 tegra_screen_get_vendor(struct pipe_screen *pscreen)
64 {
65    return "NVIDIA";
66 }
67 
68 static const char *
tegra_screen_get_device_vendor(struct pipe_screen * pscreen)69 tegra_screen_get_device_vendor(struct pipe_screen *pscreen)
70 {
71    return "NVIDIA";
72 }
73 
74 static int
tegra_screen_get_param(struct pipe_screen * pscreen,enum pipe_cap param)75 tegra_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
76 {
77    struct tegra_screen *screen = to_tegra_screen(pscreen);
78 
79    return screen->gpu->get_param(screen->gpu, param);
80 }
81 
82 static float
tegra_screen_get_paramf(struct pipe_screen * pscreen,enum pipe_capf param)83 tegra_screen_get_paramf(struct pipe_screen *pscreen, enum pipe_capf param)
84 {
85    struct tegra_screen *screen = to_tegra_screen(pscreen);
86 
87    return screen->gpu->get_paramf(screen->gpu, param);
88 }
89 
90 static int
tegra_screen_get_shader_param(struct pipe_screen * pscreen,unsigned shader,enum pipe_shader_cap param)91 tegra_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
92                               enum pipe_shader_cap param)
93 {
94    struct tegra_screen *screen = to_tegra_screen(pscreen);
95 
96    return screen->gpu->get_shader_param(screen->gpu, shader, param);
97 }
98 
99 static int
tegra_screen_get_video_param(struct pipe_screen * pscreen,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint,enum pipe_video_cap param)100 tegra_screen_get_video_param(struct pipe_screen *pscreen,
101                              enum pipe_video_profile profile,
102                              enum pipe_video_entrypoint entrypoint,
103                              enum pipe_video_cap param)
104 {
105    struct tegra_screen *screen = to_tegra_screen(pscreen);
106 
107    return screen->gpu->get_video_param(screen->gpu, profile, entrypoint,
108                                        param);
109 }
110 
111 static int
tegra_screen_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir_type,enum pipe_compute_cap param,void * retp)112 tegra_screen_get_compute_param(struct pipe_screen *pscreen,
113                                enum pipe_shader_ir ir_type,
114                                enum pipe_compute_cap param,
115                                void *retp)
116 {
117    struct tegra_screen *screen = to_tegra_screen(pscreen);
118 
119    return screen->gpu->get_compute_param(screen->gpu, ir_type, param,
120                                          retp);
121 }
122 
123 static uint64_t
tegra_screen_get_timestamp(struct pipe_screen * pscreen)124 tegra_screen_get_timestamp(struct pipe_screen *pscreen)
125 {
126    struct tegra_screen *screen = to_tegra_screen(pscreen);
127 
128    return screen->gpu->get_timestamp(screen->gpu);
129 }
130 
131 static bool
tegra_screen_is_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_texture_target target,unsigned sample_count,unsigned storage_sample_count,unsigned usage)132 tegra_screen_is_format_supported(struct pipe_screen *pscreen,
133                                  enum pipe_format format,
134                                  enum pipe_texture_target target,
135                                  unsigned sample_count,
136                                  unsigned storage_sample_count,
137                                  unsigned usage)
138 {
139    struct tegra_screen *screen = to_tegra_screen(pscreen);
140 
141    return screen->gpu->is_format_supported(screen->gpu, format, target,
142                                            sample_count, storage_sample_count,
143                                            usage);
144 }
145 
146 static bool
tegra_screen_is_video_format_supported(struct pipe_screen * pscreen,enum pipe_format format,enum pipe_video_profile profile,enum pipe_video_entrypoint entrypoint)147 tegra_screen_is_video_format_supported(struct pipe_screen *pscreen,
148                                        enum pipe_format format,
149                                        enum pipe_video_profile profile,
150                                        enum pipe_video_entrypoint entrypoint)
151 {
152    struct tegra_screen *screen = to_tegra_screen(pscreen);
153 
154    return screen->gpu->is_video_format_supported(screen->gpu, format, profile,
155                                                  entrypoint);
156 }
157 
158 static bool
tegra_screen_can_create_resource(struct pipe_screen * pscreen,const struct pipe_resource * template)159 tegra_screen_can_create_resource(struct pipe_screen *pscreen,
160                                  const struct pipe_resource *template)
161 {
162    struct tegra_screen *screen = to_tegra_screen(pscreen);
163 
164    return screen->gpu->can_create_resource(screen->gpu, template);
165 }
166 
tegra_screen_import_resource(struct tegra_screen * screen,struct tegra_resource * resource)167 static int tegra_screen_import_resource(struct tegra_screen *screen,
168                                         struct tegra_resource *resource)
169 {
170    struct winsys_handle handle;
171    bool status;
172    int fd, err;
173 
174    memset(&handle, 0, sizeof(handle));
175    handle.modifier = DRM_FORMAT_MOD_INVALID;
176    handle.type = WINSYS_HANDLE_TYPE_FD;
177 
178    status = screen->gpu->resource_get_handle(screen->gpu, NULL, resource->gpu,
179                                              &handle, 0);
180    if (!status)
181       return -EINVAL;
182 
183    assert(handle.modifier != DRM_FORMAT_MOD_INVALID);
184 
185    if (handle.modifier == DRM_FORMAT_MOD_INVALID) {
186       close(handle.handle);
187       return -EINVAL;
188    }
189 
190    resource->modifier = handle.modifier;
191    resource->stride = handle.stride;
192    fd = handle.handle;
193 
194    err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle);
195    if (err < 0)
196       err = -errno;
197 
198    close(fd);
199 
200    return err;
201 }
202 
203 static struct pipe_resource *
tegra_screen_resource_create(struct pipe_screen * pscreen,const struct pipe_resource * template)204 tegra_screen_resource_create(struct pipe_screen *pscreen,
205                              const struct pipe_resource *template)
206 {
207    struct tegra_screen *screen = to_tegra_screen(pscreen);
208    uint64_t modifier = DRM_FORMAT_MOD_INVALID;
209    struct tegra_resource *resource;
210    int err;
211 
212    resource = calloc(1, sizeof(*resource));
213    if (!resource)
214       return NULL;
215 
216    /*
217     * Applications that create scanout resources without modifiers are very
218     * unlikely to support modifiers at all. In that case the resources need
219     * to be created with a pitch-linear layout so that they can be properly
220     * shared with scanout hardware.
221     *
222     * Technically it is possible for applications to create resources without
223     * specifying a modifier but still query the modifier associated with the
224     * resource (e.g. using gbm_bo_get_modifier()) before handing it to the
225     * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL).
226     */
227    if (template->bind & PIPE_BIND_SCANOUT)
228       modifier = DRM_FORMAT_MOD_LINEAR;
229 
230    resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
231                                                                template,
232                                                                &modifier, 1);
233    if (!resource->gpu)
234       goto free;
235 
236    /* import scanout buffers for display */
237    if (template->bind & PIPE_BIND_SCANOUT) {
238       err = tegra_screen_import_resource(screen, resource);
239       if (err < 0)
240          goto destroy;
241    }
242 
243    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
244    pipe_reference_init(&resource->base.reference, 1);
245    resource->base.screen = &screen->base;
246 
247    return &resource->base;
248 
249 destroy:
250    screen->gpu->resource_destroy(screen->gpu, resource->gpu);
251 free:
252    free(resource);
253    return NULL;
254 }
255 
256 /* XXX */
257 static struct pipe_resource *
tegra_screen_resource_create_front(struct pipe_screen * pscreen,const struct pipe_resource * template,const void * map_front_private)258 tegra_screen_resource_create_front(struct pipe_screen *pscreen,
259                                    const struct pipe_resource *template,
260                                    const void *map_front_private)
261 {
262    struct tegra_screen *screen = to_tegra_screen(pscreen);
263    struct pipe_resource *resource;
264 
265    resource = screen->gpu->resource_create_front(screen->gpu, template,
266                                                  map_front_private);
267    if (resource)
268       resource->screen = pscreen;
269 
270    return resource;
271 }
272 
273 static struct pipe_resource *
tegra_screen_resource_from_handle(struct pipe_screen * pscreen,const struct pipe_resource * template,struct winsys_handle * handle,unsigned usage)274 tegra_screen_resource_from_handle(struct pipe_screen *pscreen,
275                                   const struct pipe_resource *template,
276                                   struct winsys_handle *handle,
277                                   unsigned usage)
278 {
279    struct tegra_screen *screen = to_tegra_screen(pscreen);
280    struct tegra_resource *resource;
281 
282    resource = calloc(1, sizeof(*resource));
283    if (!resource)
284       return NULL;
285 
286    resource->gpu = screen->gpu->resource_from_handle(screen->gpu, template,
287                                                      handle, usage);
288    if (!resource->gpu) {
289       free(resource);
290       return NULL;
291    }
292 
293    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
294    pipe_reference_init(&resource->base.reference, 1);
295    resource->base.screen = &screen->base;
296 
297    return &resource->base;
298 }
299 
300 /* XXX */
301 static struct pipe_resource *
tegra_screen_resource_from_user_memory(struct pipe_screen * pscreen,const struct pipe_resource * template,void * buffer)302 tegra_screen_resource_from_user_memory(struct pipe_screen *pscreen,
303                                        const struct pipe_resource *template,
304                                        void *buffer)
305 {
306    struct tegra_screen *screen = to_tegra_screen(pscreen);
307    struct pipe_resource *resource;
308 
309    resource = screen->gpu->resource_from_user_memory(screen->gpu, template,
310                                                      buffer);
311    if (resource)
312       resource->screen = pscreen;
313 
314    return resource;
315 }
316 
317 static bool
tegra_screen_resource_get_handle(struct pipe_screen * pscreen,struct pipe_context * pcontext,struct pipe_resource * presource,struct winsys_handle * handle,unsigned usage)318 tegra_screen_resource_get_handle(struct pipe_screen *pscreen,
319                                  struct pipe_context *pcontext,
320                                  struct pipe_resource *presource,
321                                  struct winsys_handle *handle,
322                                  unsigned usage)
323 {
324    struct tegra_resource *resource = to_tegra_resource(presource);
325    struct tegra_context *context = to_tegra_context(pcontext);
326    struct tegra_screen *screen = to_tegra_screen(pscreen);
327    bool ret = true;
328 
329    /*
330     * Assume that KMS handles for scanout resources will only ever be used
331     * to pass buffers into Tegra DRM for display. In all other cases, return
332     * the Nouveau handle, assuming they will be used for sharing in DRI2/3.
333     */
334    if (handle->type == WINSYS_HANDLE_TYPE_KMS &&
335        presource->bind & PIPE_BIND_SCANOUT) {
336       handle->modifier = resource->modifier;
337       handle->handle = resource->handle;
338       handle->stride = resource->stride;
339    } else {
340       ret = screen->gpu->resource_get_handle(screen->gpu,
341                                              context ? context->gpu : NULL,
342                                              resource->gpu, handle, usage);
343    }
344 
345    return ret;
346 }
347 
348 static void
tegra_screen_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * presource)349 tegra_screen_resource_destroy(struct pipe_screen *pscreen,
350                               struct pipe_resource *presource)
351 {
352    struct tegra_resource *resource = to_tegra_resource(presource);
353 
354    pipe_resource_reference(&resource->gpu, NULL);
355    free(resource);
356 }
357 
358 static void
tegra_screen_flush_frontbuffer(struct pipe_screen * pscreen,struct pipe_resource * resource,unsigned int level,unsigned int layer,void * winsys_drawable_handle,struct pipe_box * box)359 tegra_screen_flush_frontbuffer(struct pipe_screen *pscreen,
360                                struct pipe_resource *resource,
361                                unsigned int level,
362                                unsigned int layer,
363                                void *winsys_drawable_handle,
364                                struct pipe_box *box)
365 {
366    struct tegra_screen *screen = to_tegra_screen(pscreen);
367 
368    screen->gpu->flush_frontbuffer(screen->gpu, resource, level, layer,
369                                   winsys_drawable_handle, box);
370 }
371 
372 static void
tegra_screen_fence_reference(struct pipe_screen * pscreen,struct pipe_fence_handle ** ptr,struct pipe_fence_handle * fence)373 tegra_screen_fence_reference(struct pipe_screen *pscreen,
374                              struct pipe_fence_handle **ptr,
375                              struct pipe_fence_handle *fence)
376 {
377    struct tegra_screen *screen = to_tegra_screen(pscreen);
378 
379    screen->gpu->fence_reference(screen->gpu, ptr, fence);
380 }
381 
382 static bool
tegra_screen_fence_finish(struct pipe_screen * pscreen,struct pipe_context * pcontext,struct pipe_fence_handle * fence,uint64_t timeout)383 tegra_screen_fence_finish(struct pipe_screen *pscreen,
384                           struct pipe_context *pcontext,
385                           struct pipe_fence_handle *fence,
386                           uint64_t timeout)
387 {
388    struct tegra_context *context = to_tegra_context(pcontext);
389    struct tegra_screen *screen = to_tegra_screen(pscreen);
390 
391    return screen->gpu->fence_finish(screen->gpu,
392                                     context ? context->gpu : NULL,
393                                     fence, timeout);
394 }
395 
396 static int
tegra_screen_fence_get_fd(struct pipe_screen * pscreen,struct pipe_fence_handle * fence)397 tegra_screen_fence_get_fd(struct pipe_screen *pscreen,
398                           struct pipe_fence_handle *fence)
399 {
400    struct tegra_screen *screen = to_tegra_screen(pscreen);
401 
402    return screen->gpu->fence_get_fd(screen->gpu, fence);
403 }
404 
405 static int
tegra_screen_get_driver_query_info(struct pipe_screen * pscreen,unsigned int index,struct pipe_driver_query_info * info)406 tegra_screen_get_driver_query_info(struct pipe_screen *pscreen,
407                                    unsigned int index,
408                                    struct pipe_driver_query_info *info)
409 {
410    struct tegra_screen *screen = to_tegra_screen(pscreen);
411 
412    return screen->gpu->get_driver_query_info(screen->gpu, index, info);
413 }
414 
415 static int
tegra_screen_get_driver_query_group_info(struct pipe_screen * pscreen,unsigned int index,struct pipe_driver_query_group_info * info)416 tegra_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
417                                          unsigned int index,
418                                          struct pipe_driver_query_group_info *info)
419 {
420    struct tegra_screen *screen = to_tegra_screen(pscreen);
421 
422    return screen->gpu->get_driver_query_group_info(screen->gpu, index, info);
423 }
424 
425 static void
tegra_screen_query_memory_info(struct pipe_screen * pscreen,struct pipe_memory_info * info)426 tegra_screen_query_memory_info(struct pipe_screen *pscreen,
427                                struct pipe_memory_info *info)
428 {
429    struct tegra_screen *screen = to_tegra_screen(pscreen);
430 
431    screen->gpu->query_memory_info(screen->gpu, info);
432 }
433 
434 static const void *
tegra_screen_get_compiler_options(struct pipe_screen * pscreen,enum pipe_shader_ir ir,unsigned int shader)435 tegra_screen_get_compiler_options(struct pipe_screen *pscreen,
436                                   enum pipe_shader_ir ir,
437                                   unsigned int shader)
438 {
439    struct tegra_screen *screen = to_tegra_screen(pscreen);
440    const void *options = NULL;
441 
442    if (screen->gpu->get_compiler_options)
443       options = screen->gpu->get_compiler_options(screen->gpu, ir, shader);
444 
445    return options;
446 }
447 
448 static struct disk_cache *
tegra_screen_get_disk_shader_cache(struct pipe_screen * pscreen)449 tegra_screen_get_disk_shader_cache(struct pipe_screen *pscreen)
450 {
451    struct tegra_screen *screen = to_tegra_screen(pscreen);
452 
453    return screen->gpu->get_disk_shader_cache(screen->gpu);
454 }
455 
456 static struct pipe_resource *
tegra_screen_resource_create_with_modifiers(struct pipe_screen * pscreen,const struct pipe_resource * template,const uint64_t * modifiers,int count)457 tegra_screen_resource_create_with_modifiers(struct pipe_screen *pscreen,
458                                             const struct pipe_resource *template,
459                                             const uint64_t *modifiers,
460                                             int count)
461 {
462    struct tegra_screen *screen = to_tegra_screen(pscreen);
463    struct pipe_resource tmpl = *template;
464    struct tegra_resource *resource;
465    int err;
466 
467    resource = calloc(1, sizeof(*resource));
468    if (!resource)
469       return NULL;
470 
471    /*
472     * Assume that resources created with modifiers will always be used for
473     * scanout. This is necessary because some of the APIs that are used to
474     * create resources with modifiers (e.g. gbm_bo_create_with_modifiers())
475     * can't pass along usage information. Adding that capability might be
476     * worth adding to remove this ambiguity. Not all future use-cases that
477     * involve modifiers may always be targetting scanout hardware.
478     */
479    tmpl.bind |= PIPE_BIND_SCANOUT;
480 
481    resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
482                                                                &tmpl,
483                                                                modifiers,
484                                                                count);
485    if (!resource->gpu)
486       goto free;
487 
488    err = tegra_screen_import_resource(screen, resource);
489    if (err < 0)
490       goto destroy;
491 
492    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
493    pipe_reference_init(&resource->base.reference, 1);
494    resource->base.screen = &screen->base;
495 
496    return &resource->base;
497 
498 destroy:
499    screen->gpu->resource_destroy(screen->gpu, resource->gpu);
500 free:
501    free(resource);
502    return NULL;
503 }
504 
tegra_screen_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format format,int max,uint64_t * modifiers,unsigned int * external_only,int * count)505 static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
506                                                 enum pipe_format format,
507                                                 int max, uint64_t *modifiers,
508                                                 unsigned int *external_only,
509                                                 int *count)
510 {
511    struct tegra_screen *screen = to_tegra_screen(pscreen);
512 
513    screen->gpu->query_dmabuf_modifiers(screen->gpu, format, max, modifiers,
514                                        external_only, count);
515 }
516 
517 static struct pipe_memory_object *
tegra_screen_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * handle,bool dedicated)518 tegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen,
519                                        struct winsys_handle *handle,
520                                        bool dedicated)
521 {
522    struct tegra_screen *screen = to_tegra_screen(pscreen);
523 
524    return screen->gpu->memobj_create_from_handle(screen->gpu, handle,
525                                                  dedicated);
526 }
527 
528 struct pipe_screen *
tegra_screen_create(int fd)529 tegra_screen_create(int fd)
530 {
531    struct tegra_screen *screen;
532 
533    screen = calloc(1, sizeof(*screen));
534    if (!screen)
535       return NULL;
536 
537    screen->fd = fd;
538 
539    screen->gpu_fd = loader_open_render_node("nouveau");
540    if (screen->gpu_fd < 0) {
541       if (errno != ENOENT)
542          fprintf(stderr, "failed to open GPU device: %s\n", strerror(errno));
543 
544       free(screen);
545       return NULL;
546    }
547 
548    screen->gpu = nouveau_drm_screen_create(screen->gpu_fd);
549    if (!screen->gpu) {
550       fprintf(stderr, "failed to create GPU screen\n");
551       close(screen->gpu_fd);
552       free(screen);
553       return NULL;
554    }
555 
556    screen->base.destroy = tegra_screen_destroy;
557    screen->base.get_name = tegra_screen_get_name;
558    screen->base.get_vendor = tegra_screen_get_vendor;
559    screen->base.get_device_vendor = tegra_screen_get_device_vendor;
560    screen->base.get_param = tegra_screen_get_param;
561    screen->base.get_paramf = tegra_screen_get_paramf;
562    screen->base.get_shader_param = tegra_screen_get_shader_param;
563    screen->base.get_video_param = tegra_screen_get_video_param;
564    screen->base.get_compute_param = tegra_screen_get_compute_param;
565    screen->base.get_timestamp = tegra_screen_get_timestamp;
566    screen->base.context_create = tegra_screen_context_create;
567    screen->base.is_format_supported = tegra_screen_is_format_supported;
568    screen->base.is_video_format_supported = tegra_screen_is_video_format_supported;
569 
570    /* allow fallback implementation if GPU driver doesn't implement it */
571    if (screen->gpu->can_create_resource)
572       screen->base.can_create_resource = tegra_screen_can_create_resource;
573 
574    screen->base.resource_create = tegra_screen_resource_create;
575    screen->base.resource_create_front = tegra_screen_resource_create_front;
576    screen->base.resource_from_handle = tegra_screen_resource_from_handle;
577    screen->base.resource_from_user_memory = tegra_screen_resource_from_user_memory;
578    screen->base.resource_get_handle = tegra_screen_resource_get_handle;
579    screen->base.resource_destroy = tegra_screen_resource_destroy;
580 
581    screen->base.flush_frontbuffer = tegra_screen_flush_frontbuffer;
582    screen->base.fence_reference = tegra_screen_fence_reference;
583    screen->base.fence_finish = tegra_screen_fence_finish;
584    screen->base.fence_get_fd = tegra_screen_fence_get_fd;
585 
586    screen->base.get_driver_query_info = tegra_screen_get_driver_query_info;
587    screen->base.get_driver_query_group_info = tegra_screen_get_driver_query_group_info;
588    screen->base.query_memory_info = tegra_screen_query_memory_info;
589 
590    screen->base.get_compiler_options = tegra_screen_get_compiler_options;
591    screen->base.get_disk_shader_cache = tegra_screen_get_disk_shader_cache;
592 
593    screen->base.resource_create_with_modifiers = tegra_screen_resource_create_with_modifiers;
594    screen->base.query_dmabuf_modifiers = tegra_screen_query_dmabuf_modifiers;
595    screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle;
596 
597    return &screen->base;
598 }
599