• 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/format/u_format.h"
39 #include "util/u_inlines.h"
40 
41 #include "frontend/drm_driver.h"
42 
43 #include "nouveau/drm/nouveau_drm_public.h"
44 
45 #include "tegra_context.h"
46 #include "tegra_resource.h"
47 #include "tegra_screen.h"
48 
tegra_screen_destroy(struct pipe_screen * pscreen)49 static void tegra_screen_destroy(struct pipe_screen *pscreen)
50 {
51    struct tegra_screen *screen = to_tegra_screen(pscreen);
52 
53    screen->gpu->destroy(screen->gpu);
54    free(pscreen);
55 }
56 
57 static const char *
tegra_screen_get_name(struct pipe_screen * pscreen)58 tegra_screen_get_name(struct pipe_screen *pscreen)
59 {
60    return "tegra";
61 }
62 
63 static const char *
tegra_screen_get_vendor(struct pipe_screen * pscreen)64 tegra_screen_get_vendor(struct pipe_screen *pscreen)
65 {
66    return "NVIDIA";
67 }
68 
69 static const char *
tegra_screen_get_device_vendor(struct pipe_screen * pscreen)70 tegra_screen_get_device_vendor(struct pipe_screen *pscreen)
71 {
72    return "NVIDIA";
73 }
74 
75 static int
tegra_screen_get_shader_param(struct pipe_screen * pscreen,enum pipe_shader_type shader,enum pipe_shader_cap param)76 tegra_screen_get_shader_param(struct pipe_screen *pscreen, enum pipe_shader_type shader,
77                               enum pipe_shader_cap param)
78 {
79    struct tegra_screen *screen = to_tegra_screen(pscreen);
80 
81    return screen->gpu->get_shader_param(screen->gpu, shader, param);
82 }
83 
84 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)85 tegra_screen_get_video_param(struct pipe_screen *pscreen,
86                              enum pipe_video_profile profile,
87                              enum pipe_video_entrypoint entrypoint,
88                              enum pipe_video_cap param)
89 {
90    struct tegra_screen *screen = to_tegra_screen(pscreen);
91 
92    return screen->gpu->get_video_param(screen->gpu, profile, entrypoint,
93                                        param);
94 }
95 
96 static int
tegra_screen_get_compute_param(struct pipe_screen * pscreen,enum pipe_shader_ir ir_type,enum pipe_compute_cap param,void * retp)97 tegra_screen_get_compute_param(struct pipe_screen *pscreen,
98                                enum pipe_shader_ir ir_type,
99                                enum pipe_compute_cap param,
100                                void *retp)
101 {
102    struct tegra_screen *screen = to_tegra_screen(pscreen);
103 
104    return screen->gpu->get_compute_param(screen->gpu, ir_type, param,
105                                          retp);
106 }
107 
108 static uint64_t
tegra_screen_get_timestamp(struct pipe_screen * pscreen)109 tegra_screen_get_timestamp(struct pipe_screen *pscreen)
110 {
111    struct tegra_screen *screen = to_tegra_screen(pscreen);
112 
113    return screen->gpu->get_timestamp(screen->gpu);
114 }
115 
116 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)117 tegra_screen_is_format_supported(struct pipe_screen *pscreen,
118                                  enum pipe_format format,
119                                  enum pipe_texture_target target,
120                                  unsigned sample_count,
121                                  unsigned storage_sample_count,
122                                  unsigned usage)
123 {
124    struct tegra_screen *screen = to_tegra_screen(pscreen);
125 
126    return screen->gpu->is_format_supported(screen->gpu, format, target,
127                                            sample_count, storage_sample_count,
128                                            usage);
129 }
130 
131 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)132 tegra_screen_is_video_format_supported(struct pipe_screen *pscreen,
133                                        enum pipe_format format,
134                                        enum pipe_video_profile profile,
135                                        enum pipe_video_entrypoint entrypoint)
136 {
137    struct tegra_screen *screen = to_tegra_screen(pscreen);
138 
139    return screen->gpu->is_video_format_supported(screen->gpu, format, profile,
140                                                  entrypoint);
141 }
142 
143 static bool
tegra_screen_can_create_resource(struct pipe_screen * pscreen,const struct pipe_resource * template)144 tegra_screen_can_create_resource(struct pipe_screen *pscreen,
145                                  const struct pipe_resource *template)
146 {
147    struct tegra_screen *screen = to_tegra_screen(pscreen);
148 
149    return screen->gpu->can_create_resource(screen->gpu, template);
150 }
151 
tegra_screen_import_resource(struct tegra_screen * screen,struct tegra_resource * resource)152 static int tegra_screen_import_resource(struct tegra_screen *screen,
153                                         struct tegra_resource *resource)
154 {
155    struct winsys_handle handle;
156    bool status;
157    int fd, err;
158 
159    memset(&handle, 0, sizeof(handle));
160    handle.modifier = DRM_FORMAT_MOD_INVALID;
161    handle.type = WINSYS_HANDLE_TYPE_FD;
162 
163    status = screen->gpu->resource_get_handle(screen->gpu, NULL, resource->gpu,
164                                              &handle, 0);
165    if (!status)
166       return -EINVAL;
167 
168    assert(handle.modifier != DRM_FORMAT_MOD_INVALID);
169 
170    if (handle.modifier == DRM_FORMAT_MOD_INVALID) {
171       close(handle.handle);
172       return -EINVAL;
173    }
174 
175    resource->modifier = handle.modifier;
176    resource->stride = handle.stride;
177    fd = handle.handle;
178 
179    err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle);
180    if (err < 0)
181       err = -errno;
182 
183    close(fd);
184 
185    return err;
186 }
187 
188 static struct pipe_resource *
tegra_screen_resource_create(struct pipe_screen * pscreen,const struct pipe_resource * template)189 tegra_screen_resource_create(struct pipe_screen *pscreen,
190                              const struct pipe_resource *template)
191 {
192    struct tegra_screen *screen = to_tegra_screen(pscreen);
193    uint64_t modifier = DRM_FORMAT_MOD_INVALID;
194    struct tegra_resource *resource;
195    int err;
196 
197    resource = calloc(1, sizeof(*resource));
198    if (!resource)
199       return NULL;
200 
201    /*
202     * Applications that create scanout resources without modifiers are very
203     * unlikely to support modifiers at all. In that case the resources need
204     * to be created with a pitch-linear layout so that they can be properly
205     * shared with scanout hardware.
206     *
207     * Technically it is possible for applications to create resources without
208     * specifying a modifier but still query the modifier associated with the
209     * resource (e.g. using gbm_bo_get_modifier()) before handing it to the
210     * framebuffer creation API (such as the DRM_IOCTL_MODE_ADDFB2 IOCTL).
211     */
212    if (template->bind & PIPE_BIND_SCANOUT)
213       modifier = DRM_FORMAT_MOD_LINEAR;
214 
215    resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
216                                                                template,
217                                                                &modifier, 1);
218    if (!resource->gpu)
219       goto free;
220 
221    /* import scanout buffers for display */
222    if (template->bind & PIPE_BIND_SCANOUT) {
223       err = tegra_screen_import_resource(screen, resource);
224       if (err < 0)
225          goto destroy;
226    }
227 
228    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
229    pipe_reference_init(&resource->base.reference, 1);
230    resource->base.screen = &screen->base;
231 
232    /* use private reference count for wrapped resources */
233    resource->gpu->reference.count += 100000000;
234    resource->refcount = 100000000;
235 
236    return &resource->base;
237 
238 destroy:
239    screen->gpu->resource_destroy(screen->gpu, resource->gpu);
240 free:
241    free(resource);
242    return NULL;
243 }
244 
245 /* XXX */
246 static struct pipe_resource *
tegra_screen_resource_create_front(struct pipe_screen * pscreen,const struct pipe_resource * template,const void * map_front_private)247 tegra_screen_resource_create_front(struct pipe_screen *pscreen,
248                                    const struct pipe_resource *template,
249                                    const void *map_front_private)
250 {
251    struct tegra_screen *screen = to_tegra_screen(pscreen);
252    struct pipe_resource *resource;
253 
254    resource = screen->gpu->resource_create_front(screen->gpu, template,
255                                                  map_front_private);
256    if (resource)
257       resource->screen = pscreen;
258 
259    return resource;
260 }
261 
262 static struct pipe_resource *
tegra_screen_resource_from_handle(struct pipe_screen * pscreen,const struct pipe_resource * template,struct winsys_handle * handle,unsigned usage)263 tegra_screen_resource_from_handle(struct pipe_screen *pscreen,
264                                   const struct pipe_resource *template,
265                                   struct winsys_handle *handle,
266                                   unsigned usage)
267 {
268    struct tegra_screen *screen = to_tegra_screen(pscreen);
269    struct tegra_resource *resource;
270 
271    resource = calloc(1, sizeof(*resource));
272    if (!resource)
273       return NULL;
274 
275    resource->gpu = screen->gpu->resource_from_handle(screen->gpu, template,
276                                                      handle, usage);
277    if (!resource->gpu) {
278       free(resource);
279       return NULL;
280    }
281 
282    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
283    pipe_reference_init(&resource->base.reference, 1);
284    resource->base.screen = &screen->base;
285 
286    return &resource->base;
287 }
288 
289 /* XXX */
290 static struct pipe_resource *
tegra_screen_resource_from_user_memory(struct pipe_screen * pscreen,const struct pipe_resource * template,void * buffer)291 tegra_screen_resource_from_user_memory(struct pipe_screen *pscreen,
292                                        const struct pipe_resource *template,
293                                        void *buffer)
294 {
295    struct tegra_screen *screen = to_tegra_screen(pscreen);
296    struct pipe_resource *resource;
297 
298    resource = screen->gpu->resource_from_user_memory(screen->gpu, template,
299                                                      buffer);
300    if (resource)
301       resource->screen = pscreen;
302 
303    return resource;
304 }
305 
306 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)307 tegra_screen_resource_get_handle(struct pipe_screen *pscreen,
308                                  struct pipe_context *pcontext,
309                                  struct pipe_resource *presource,
310                                  struct winsys_handle *handle,
311                                  unsigned usage)
312 {
313    struct tegra_resource *resource = to_tegra_resource(presource);
314    struct tegra_context *context = to_tegra_context(pcontext);
315    struct tegra_screen *screen = to_tegra_screen(pscreen);
316    bool ret = true;
317 
318    /*
319     * Assume that KMS handles for scanout resources will only ever be used
320     * to pass buffers into Tegra DRM for display. In all other cases, return
321     * the Nouveau handle, assuming they will be used for sharing in DRI2/3.
322     */
323    if (handle->type == WINSYS_HANDLE_TYPE_KMS &&
324        presource->bind & PIPE_BIND_SCANOUT) {
325       handle->modifier = resource->modifier;
326       handle->handle = resource->handle;
327       handle->stride = resource->stride;
328    } else {
329       ret = screen->gpu->resource_get_handle(screen->gpu,
330                                              context ? context->gpu : NULL,
331                                              resource->gpu, handle, usage);
332    }
333 
334    return ret;
335 }
336 
337 static void
tegra_screen_resource_destroy(struct pipe_screen * pscreen,struct pipe_resource * presource)338 tegra_screen_resource_destroy(struct pipe_screen *pscreen,
339                               struct pipe_resource *presource)
340 {
341    struct tegra_resource *resource = to_tegra_resource(presource);
342 
343    /* adjust private reference count */
344    p_atomic_add(&resource->gpu->reference.count, -resource->refcount);
345    pipe_resource_reference(&resource->gpu, NULL);
346    free(resource);
347 }
348 
349 static void
tegra_screen_flush_frontbuffer(struct pipe_screen * pscreen,struct pipe_context * pcontext,struct pipe_resource * resource,unsigned int level,unsigned int layer,void * winsys_drawable_handle,unsigned nboxes,struct pipe_box * box)350 tegra_screen_flush_frontbuffer(struct pipe_screen *pscreen,
351                                struct pipe_context *pcontext,
352                                struct pipe_resource *resource,
353                                unsigned int level,
354                                unsigned int layer,
355                                void *winsys_drawable_handle,
356                                unsigned nboxes,
357                                struct pipe_box *box)
358 {
359    struct tegra_screen *screen = to_tegra_screen(pscreen);
360    struct tegra_context *context = to_tegra_context(pcontext);
361 
362    /* TODO: maybe rejigger for damage regions */
363    screen->gpu->flush_frontbuffer(screen->gpu,
364                                   context ? context->gpu : NULL,
365                                   resource, level, layer,
366                                   winsys_drawable_handle, nboxes, box);
367 }
368 
369 static void
tegra_screen_fence_reference(struct pipe_screen * pscreen,struct pipe_fence_handle ** ptr,struct pipe_fence_handle * fence)370 tegra_screen_fence_reference(struct pipe_screen *pscreen,
371                              struct pipe_fence_handle **ptr,
372                              struct pipe_fence_handle *fence)
373 {
374    struct tegra_screen *screen = to_tegra_screen(pscreen);
375 
376    screen->gpu->fence_reference(screen->gpu, ptr, fence);
377 }
378 
379 static bool
tegra_screen_fence_finish(struct pipe_screen * pscreen,struct pipe_context * pcontext,struct pipe_fence_handle * fence,uint64_t timeout)380 tegra_screen_fence_finish(struct pipe_screen *pscreen,
381                           struct pipe_context *pcontext,
382                           struct pipe_fence_handle *fence,
383                           uint64_t timeout)
384 {
385    struct tegra_context *context = to_tegra_context(pcontext);
386    struct tegra_screen *screen = to_tegra_screen(pscreen);
387 
388    return screen->gpu->fence_finish(screen->gpu,
389                                     context ? context->gpu : NULL,
390                                     fence, timeout);
391 }
392 
393 static int
tegra_screen_fence_get_fd(struct pipe_screen * pscreen,struct pipe_fence_handle * fence)394 tegra_screen_fence_get_fd(struct pipe_screen *pscreen,
395                           struct pipe_fence_handle *fence)
396 {
397    struct tegra_screen *screen = to_tegra_screen(pscreen);
398 
399    return screen->gpu->fence_get_fd(screen->gpu, fence);
400 }
401 
402 static int
tegra_screen_get_driver_query_info(struct pipe_screen * pscreen,unsigned int index,struct pipe_driver_query_info * info)403 tegra_screen_get_driver_query_info(struct pipe_screen *pscreen,
404                                    unsigned int index,
405                                    struct pipe_driver_query_info *info)
406 {
407    struct tegra_screen *screen = to_tegra_screen(pscreen);
408 
409    return screen->gpu->get_driver_query_info(screen->gpu, index, info);
410 }
411 
412 static int
tegra_screen_get_driver_query_group_info(struct pipe_screen * pscreen,unsigned int index,struct pipe_driver_query_group_info * info)413 tegra_screen_get_driver_query_group_info(struct pipe_screen *pscreen,
414                                          unsigned int index,
415                                          struct pipe_driver_query_group_info *info)
416 {
417    struct tegra_screen *screen = to_tegra_screen(pscreen);
418 
419    return screen->gpu->get_driver_query_group_info(screen->gpu, index, info);
420 }
421 
422 static void
tegra_screen_query_memory_info(struct pipe_screen * pscreen,struct pipe_memory_info * info)423 tegra_screen_query_memory_info(struct pipe_screen *pscreen,
424                                struct pipe_memory_info *info)
425 {
426    struct tegra_screen *screen = to_tegra_screen(pscreen);
427 
428    screen->gpu->query_memory_info(screen->gpu, info);
429 }
430 
431 static const void *
tegra_screen_get_compiler_options(struct pipe_screen * pscreen,enum pipe_shader_ir ir,enum pipe_shader_type shader)432 tegra_screen_get_compiler_options(struct pipe_screen *pscreen,
433                                   enum pipe_shader_ir ir,
434                                   enum pipe_shader_type shader)
435 {
436    struct tegra_screen *screen = to_tegra_screen(pscreen);
437    const void *options = NULL;
438 
439    if (screen->gpu->get_compiler_options)
440       options = screen->gpu->get_compiler_options(screen->gpu, ir, shader);
441 
442    return options;
443 }
444 
445 static struct disk_cache *
tegra_screen_get_disk_shader_cache(struct pipe_screen * pscreen)446 tegra_screen_get_disk_shader_cache(struct pipe_screen *pscreen)
447 {
448    struct tegra_screen *screen = to_tegra_screen(pscreen);
449 
450    return screen->gpu->get_disk_shader_cache(screen->gpu);
451 }
452 
453 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)454 tegra_screen_resource_create_with_modifiers(struct pipe_screen *pscreen,
455                                             const struct pipe_resource *template,
456                                             const uint64_t *modifiers,
457                                             int count)
458 {
459    struct tegra_screen *screen = to_tegra_screen(pscreen);
460    struct pipe_resource tmpl = *template;
461    struct tegra_resource *resource;
462    int err;
463 
464    resource = calloc(1, sizeof(*resource));
465    if (!resource)
466       return NULL;
467 
468    /*
469     * Assume that resources created with modifiers will always be used for
470     * scanout. This is necessary because some of the APIs that are used to
471     * create resources with modifiers (e.g. gbm_bo_create_with_modifiers())
472     * can't pass along usage information. Adding that capability might be
473     * worth adding to remove this ambiguity. Not all future use-cases that
474     * involve modifiers may always be targetting scanout hardware.
475     */
476    tmpl.bind |= PIPE_BIND_SCANOUT;
477 
478    resource->gpu = screen->gpu->resource_create_with_modifiers(screen->gpu,
479                                                                &tmpl,
480                                                                modifiers,
481                                                                count);
482    if (!resource->gpu)
483       goto free;
484 
485    err = tegra_screen_import_resource(screen, resource);
486    if (err < 0)
487       goto destroy;
488 
489    memcpy(&resource->base, resource->gpu, sizeof(*resource->gpu));
490    pipe_reference_init(&resource->base.reference, 1);
491    resource->base.screen = &screen->base;
492 
493    return &resource->base;
494 
495 destroy:
496    screen->gpu->resource_destroy(screen->gpu, resource->gpu);
497 free:
498    free(resource);
499    return NULL;
500 }
501 
tegra_screen_query_dmabuf_modifiers(struct pipe_screen * pscreen,enum pipe_format format,int max,uint64_t * modifiers,unsigned int * external_only,int * count)502 static void tegra_screen_query_dmabuf_modifiers(struct pipe_screen *pscreen,
503                                                 enum pipe_format format,
504                                                 int max, uint64_t *modifiers,
505                                                 unsigned int *external_only,
506                                                 int *count)
507 {
508    struct tegra_screen *screen = to_tegra_screen(pscreen);
509 
510    screen->gpu->query_dmabuf_modifiers(screen->gpu, format, max, modifiers,
511                                        external_only, count);
512 }
513 
514 static bool
tegra_screen_is_dmabuf_modifier_supported(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format,bool * external_only)515 tegra_screen_is_dmabuf_modifier_supported(struct pipe_screen *pscreen,
516                                           uint64_t modifier,
517                                           enum pipe_format format,
518                                           bool *external_only)
519 {
520    struct tegra_screen *screen = to_tegra_screen(pscreen);
521 
522    return screen->gpu->is_dmabuf_modifier_supported(screen->gpu, modifier,
523                                                     format, external_only);
524 }
525 
526 static unsigned int
tegra_screen_get_dmabuf_modifier_planes(struct pipe_screen * pscreen,uint64_t modifier,enum pipe_format format)527 tegra_screen_get_dmabuf_modifier_planes(struct pipe_screen *pscreen,
528                                         uint64_t modifier,
529                                         enum pipe_format format)
530 {
531    struct tegra_screen *screen = to_tegra_screen(pscreen);
532 
533    return screen->gpu->get_dmabuf_modifier_planes ?
534       screen->gpu->get_dmabuf_modifier_planes(screen->gpu, modifier, format) :
535       util_format_get_num_planes(format);
536 }
537 
538 static struct pipe_memory_object *
tegra_screen_memobj_create_from_handle(struct pipe_screen * pscreen,struct winsys_handle * handle,bool dedicated)539 tegra_screen_memobj_create_from_handle(struct pipe_screen *pscreen,
540                                        struct winsys_handle *handle,
541                                        bool dedicated)
542 {
543    struct tegra_screen *screen = to_tegra_screen(pscreen);
544 
545    return screen->gpu->memobj_create_from_handle(screen->gpu, handle,
546                                                  dedicated);
547 }
548 
549 static int
tegra_screen_get_fd(struct pipe_screen * pscreen)550 tegra_screen_get_fd(struct pipe_screen *pscreen)
551 {
552    struct tegra_screen *screen = to_tegra_screen(pscreen);
553 
554    return screen->fd;
555 }
556 
557 struct pipe_screen *
tegra_screen_create(int fd)558 tegra_screen_create(int fd)
559 {
560    struct tegra_screen *screen;
561    const char * const drivers[] = {"nouveau"};
562 
563    screen = calloc(1, sizeof(*screen));
564    if (!screen)
565       return NULL;
566 
567    screen->fd = fd;
568 
569    screen->gpu_fd =
570       loader_open_render_node_platform_device(drivers, ARRAY_SIZE(drivers));
571    if (screen->gpu_fd < 0) {
572       if (errno != ENOENT)
573          fprintf(stderr, "failed to open GPU device: %s\n", strerror(errno));
574 
575       free(screen);
576       return NULL;
577    }
578 
579    screen->gpu = nouveau_drm_screen_create(screen->gpu_fd);
580    if (!screen->gpu) {
581       fprintf(stderr, "failed to create GPU screen\n");
582       close(screen->gpu_fd);
583       free(screen);
584       return NULL;
585    }
586 
587    screen->base.destroy = tegra_screen_destroy;
588    screen->base.get_name = tegra_screen_get_name;
589    screen->base.get_vendor = tegra_screen_get_vendor;
590    screen->base.get_device_vendor = tegra_screen_get_device_vendor;
591    screen->base.get_screen_fd = tegra_screen_get_fd;
592    screen->base.get_shader_param = tegra_screen_get_shader_param;
593    screen->base.get_video_param = tegra_screen_get_video_param;
594    screen->base.get_compute_param = tegra_screen_get_compute_param;
595    screen->base.get_timestamp = tegra_screen_get_timestamp;
596    screen->base.context_create = tegra_screen_context_create;
597    screen->base.is_format_supported = tegra_screen_is_format_supported;
598    screen->base.is_video_format_supported = tegra_screen_is_video_format_supported;
599 
600    /* allow fallback implementation if GPU driver doesn't implement it */
601    if (screen->gpu->can_create_resource)
602       screen->base.can_create_resource = tegra_screen_can_create_resource;
603 
604    screen->base.resource_create = tegra_screen_resource_create;
605    screen->base.resource_create_front = tegra_screen_resource_create_front;
606    screen->base.resource_from_handle = tegra_screen_resource_from_handle;
607    screen->base.resource_from_user_memory = tegra_screen_resource_from_user_memory;
608    screen->base.resource_get_handle = tegra_screen_resource_get_handle;
609    screen->base.resource_destroy = tegra_screen_resource_destroy;
610 
611    screen->base.flush_frontbuffer = tegra_screen_flush_frontbuffer;
612    screen->base.fence_reference = tegra_screen_fence_reference;
613    screen->base.fence_finish = tegra_screen_fence_finish;
614    screen->base.fence_get_fd = tegra_screen_fence_get_fd;
615 
616    screen->base.get_driver_query_info = tegra_screen_get_driver_query_info;
617    screen->base.get_driver_query_group_info = tegra_screen_get_driver_query_group_info;
618    screen->base.query_memory_info = tegra_screen_query_memory_info;
619 
620    screen->base.get_compiler_options = tegra_screen_get_compiler_options;
621    screen->base.get_disk_shader_cache = tegra_screen_get_disk_shader_cache;
622 
623    screen->base.resource_create_with_modifiers = tegra_screen_resource_create_with_modifiers;
624    screen->base.query_dmabuf_modifiers = tegra_screen_query_dmabuf_modifiers;
625    screen->base.is_dmabuf_modifier_supported = tegra_screen_is_dmabuf_modifier_supported;
626    screen->base.get_dmabuf_modifier_planes = tegra_screen_get_dmabuf_modifier_planes;
627    screen->base.memobj_create_from_handle = tegra_screen_memobj_create_from_handle;
628 
629    memcpy((void *)&screen->base.caps, &screen->gpu->caps, sizeof(screen->base.caps));
630 
631    return &screen->base;
632 }
633