1/*
2 * Copyright © 2011 Intel 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,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 *    Kristian Høgsberg <krh@bitplanet.net>
26 */
27
28#ifndef EGL_DRI2_INCLUDED
29#define EGL_DRI2_INCLUDED
30
31#include <stdbool.h>
32#include <stdint.h>
33
34#ifdef HAVE_X11_PLATFORM
35#include <xcb/xcb.h>
36#include <xcb/dri2.h>
37#include <xcb/xfixes.h>
38#include <X11/Xlib-xcb.h>
39
40#ifdef HAVE_DRI3
41#include "loader_dri3_helper.h"
42#endif
43#endif
44
45#ifdef HAVE_WAYLAND_PLATFORM
46/* forward declarations to avoid pulling wayland headers everywhere */
47struct wl_egl_window;
48struct wl_event_queue;
49struct wl_callback;
50struct wl_display;
51struct wl_drm;
52struct wl_registry;
53struct wl_shm;
54struct wl_surface;
55struct zwp_linux_dmabuf_v1;
56struct zwp_linux_dmabuf_feedback_v1;
57#endif
58
59#include <GL/gl.h>
60#include <GL/internal/dri_interface.h>
61#include "kopper_interface.h"
62
63#ifdef HAVE_DRM_PLATFORM
64#include <gbm_driint.h>
65#endif
66
67#ifdef HAVE_ANDROID_PLATFORM
68#define LOG_TAG "EGL-DRI2"
69
70#include <hardware/gralloc.h>
71
72#if ANDROID_API_LEVEL >= 26
73#include <vndk/window.h>
74#else
75#include <system/window.h>
76#endif
77
78#ifdef HAVE_OHOS_PLATFORM
79#include "window.h"
80#endif
81
82#endif /* HAVE_ANDROID_PLATFORM */
83
84#include "eglconfig.h"
85#include "eglcontext.h"
86#include "egldevice.h"
87#include "egldisplay.h"
88#include "egldriver.h"
89#include "eglcurrent.h"
90#include "egllog.h"
91#include "eglsurface.h"
92#include "eglimage.h"
93#include "eglsync.h"
94
95#include "util/u_vector.h"
96#include "util/u_dynarray.h"
97#include "util/bitset.h"
98
99struct wl_buffer;
100
101struct dri2_egl_display_vtbl {
102   /* mandatory on Wayland, unused otherwise */
103   int (*authenticate)(_EGLDisplay *disp, uint32_t id);
104
105   /* mandatory */
106   _EGLSurface* (*create_window_surface)(_EGLDisplay *disp, _EGLConfig *config,
107                                         void *native_window,
108                                         const EGLint *attrib_list);
109
110   /* optional */
111   _EGLSurface* (*create_pixmap_surface)(_EGLDisplay *disp, _EGLConfig *config,
112                                         void *native_pixmap,
113                                         const EGLint *attrib_list);
114
115   /* optional */
116   _EGLSurface* (*create_pbuffer_surface)(_EGLDisplay *disp, _EGLConfig *config,
117                                          const EGLint *attrib_list);
118
119   /* mandatory */
120   EGLBoolean (*destroy_surface)(_EGLDisplay *disp, _EGLSurface *surface);
121
122   /* optional */
123   EGLBoolean (*swap_interval)(_EGLDisplay *disp, _EGLSurface *surf,
124                               EGLint interval);
125
126   /* mandatory */
127   _EGLImage* (*create_image)(_EGLDisplay *disp, _EGLContext *ctx,
128                              EGLenum target, EGLClientBuffer buffer,
129                              const EGLint *attr_list);
130
131   /* mandatory */
132   EGLBoolean (*swap_buffers)(_EGLDisplay *disp, _EGLSurface *surf);
133
134   /* optional - falls back to .swap_buffers */
135   EGLBoolean (*swap_buffers_with_damage)(_EGLDisplay *disp, _EGLSurface *surface,
136                                          const EGLint *rects, EGLint n_rects);
137
138   /* optional */
139   EGLBoolean (*swap_buffers_region)(_EGLDisplay *disp, _EGLSurface *surf,
140                                     EGLint numRects, const EGLint *rects);
141
142   /* optional */
143   EGLBoolean (*post_sub_buffer)(_EGLDisplay *disp, _EGLSurface *surf,
144                                 EGLint x, EGLint y,
145                                 EGLint width, EGLint height);
146
147   /* optional */
148   EGLBoolean (*copy_buffers)(_EGLDisplay *disp, _EGLSurface *surf,
149                              void *native_pixmap_target);
150
151   /* optional */
152   EGLint (*query_buffer_age)(_EGLDisplay *disp, _EGLSurface *surf);
153
154   /* optional */
155   EGLBoolean (*query_surface)(_EGLDisplay *disp, _EGLSurface *surf,
156                               EGLint attribute, EGLint *value);
157
158   /* optional */
159   struct wl_buffer* (*create_wayland_buffer_from_image)(_EGLDisplay *disp,
160                                                         _EGLImage *img);
161
162   /* optional */
163   EGLBoolean (*get_sync_values)(_EGLDisplay *display, _EGLSurface *surface,
164                                 EGLuint64KHR *ust, EGLuint64KHR *msc,
165                                 EGLuint64KHR *sbc);
166
167   /* mandatory */
168   __DRIdrawable *(*get_dri_drawable)(_EGLSurface *surf);
169
170   /* optional */
171   void (*close_screen_notify)(_EGLDisplay *disp);
172
173   /* Used in EGL_KHR_mutable_render_buffer to update the native window's
174    * shared buffer mode.
175    * optional
176    */
177   bool (*set_shared_buffer_mode)(_EGLDisplay *disp, _EGLSurface *surf,
178                                  bool mode);
179};
180
181#ifdef HAVE_WAYLAND_PLATFORM
182struct dri2_wl_formats {
183   unsigned int num_formats;
184
185   /* Bitmap referencing dri2_wl_visuals */
186   unsigned int *formats_bitmap;
187
188   /* Array of vectors. Contains one modifier vector per format */
189   struct u_vector *modifiers;
190};
191
192struct dmabuf_feedback_format_table {
193   unsigned int size;
194   struct {
195      uint32_t format;
196      uint32_t padding; /* unused */
197      uint64_t modifier;
198   } *data;
199};
200
201struct dmabuf_feedback_tranche {
202   dev_t target_device;
203   uint32_t flags;
204   struct dri2_wl_formats formats;
205};
206
207struct dmabuf_feedback {
208   dev_t main_device;
209   struct dmabuf_feedback_format_table format_table;
210   struct util_dynarray tranches;
211   struct dmabuf_feedback_tranche pending_tranche;
212};
213#endif
214
215struct dri2_egl_display
216{
217   const struct dri2_egl_display_vtbl *vtbl;
218
219   int dri2_major;
220   int dri2_minor;
221   __DRIscreen *dri_screen;
222   bool own_dri_screen;
223   const __DRIconfig **driver_configs;
224   void *driver;
225   const __DRIcoreExtension *core;
226   const __DRIimageDriverExtension *image_driver;
227   const __DRIdri2Extension *dri2;
228   const __DRIswrastExtension *swrast;
229   const __DRIkopperExtension *kopper;
230   const __DRI2flushExtension *flush;
231   const __DRI2flushControlExtension *flush_control;
232   const __DRItexBufferExtension *tex_buffer;
233   const __DRIimageExtension *image;
234   const __DRIrobustnessExtension *robustness;
235   const __DRI2configQueryExtension *config;
236   const __DRI2fenceExtension *fence;
237   const __DRI2bufferDamageExtension *buffer_damage;
238   const __DRI2blobExtension *blob;
239   const __DRI2rendererQueryExtension *rendererQuery;
240   const __DRI2interopExtension *interop;
241   const __DRIconfigOptionsExtension *configOptions;
242   const __DRImutableRenderBufferDriverExtension *mutable_render_buffer;
243   int fd;
244
245   /* dri2_initialize/dri2_terminate increment/decrement this count, so does
246    * dri2_make_current (tracks if there are active contexts/surfaces). */
247   int ref_count;
248
249   bool own_device;
250   bool invalidate_available;
251   int min_swap_interval;
252   int max_swap_interval;
253   int default_swap_interval;
254#ifdef HAVE_DRM_PLATFORM
255   struct gbm_dri_device *gbm_dri;
256#endif
257
258   char *driver_name;
259
260   const __DRIextension **loader_extensions;
261   const __DRIextension **driver_extensions;
262
263#ifdef HAVE_X11_PLATFORM
264   xcb_connection_t *conn;
265   xcb_screen_t *screen;
266   bool swap_available;
267#ifdef HAVE_DRI3
268   bool multibuffers_available;
269   int dri3_major_version;
270   int dri3_minor_version;
271   int present_major_version;
272   int present_minor_version;
273   struct loader_dri3_extensions loader_dri3_ext;
274#endif
275#endif
276
277#ifdef HAVE_WAYLAND_PLATFORM
278   struct wl_display *wl_dpy;
279   struct wl_display *wl_dpy_wrapper;
280   struct wl_registry *wl_registry;
281   struct wl_drm *wl_server_drm;
282   struct wl_drm *wl_drm;
283   uint32_t wl_drm_version, wl_drm_name;
284   struct wl_shm *wl_shm;
285   struct wl_event_queue *wl_queue;
286   struct zwp_linux_dmabuf_v1 *wl_dmabuf;
287   struct dri2_wl_formats formats;
288   struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
289   struct dmabuf_feedback_format_table format_table;
290   bool authenticated;
291   uint32_t capabilities;
292   char *device_name;
293#endif
294
295#ifdef HAVE_ANDROID_PLATFORM
296   const gralloc_module_t *gralloc;
297   /* gralloc vendor usage bit for front rendering */
298   uint32_t front_rendering_usage;
299#endif
300
301   bool is_render_node;
302   bool is_different_gpu;
303};
304
305struct dri2_egl_context
306{
307   _EGLContext base;
308   __DRIcontext *dri_context;
309};
310
311struct dri2_egl_surface
312{
313   _EGLSurface base;
314   __DRIdrawable *dri_drawable;
315   __DRIbuffer buffers[5];
316   bool have_fake_front;
317
318#ifdef HAVE_X11_PLATFORM
319   xcb_drawable_t drawable;
320   xcb_xfixes_region_t region;
321   int depth;
322   int bytes_per_pixel;
323   xcb_gcontext_t gc;
324   xcb_gcontext_t swapgc;
325#endif
326
327#ifdef HAVE_WAYLAND_PLATFORM
328   struct wl_egl_window *wl_win;
329   int dx;
330   int dy;
331   struct wl_event_queue *wl_queue;
332   struct wl_surface *wl_surface_wrapper;
333   struct wl_display *wl_dpy_wrapper;
334   struct wl_drm *wl_drm_wrapper;
335   struct wl_callback *throttle_callback;
336   struct zwp_linux_dmabuf_feedback_v1 *wl_dmabuf_feedback;
337   struct dmabuf_feedback dmabuf_feedback, pending_dmabuf_feedback;
338   bool compositor_using_another_device;
339   int format;
340   bool resized;
341   bool received_dmabuf_feedback;
342#endif
343
344#ifdef HAVE_DRM_PLATFORM
345   struct gbm_dri_surface *gbm_surf;
346#endif
347
348   /* EGL-owned buffers */
349   __DRIbuffer *local_buffers[__DRI_BUFFER_COUNT];
350
351#if defined(HAVE_WAYLAND_PLATFORM) || defined(HAVE_DRM_PLATFORM)
352   struct {
353#ifdef HAVE_WAYLAND_PLATFORM
354      struct wl_buffer *wl_buffer;
355      bool wl_release;
356      __DRIimage *dri_image;
357      /* for is_different_gpu case. NULL else */
358      __DRIimage *linear_copy;
359      /* for swrast */
360      void *data;
361      int data_size;
362#endif
363#ifdef HAVE_DRM_PLATFORM
364      struct gbm_bo *bo;
365#endif
366      bool locked;
367      int age;
368   } color_buffers[4], *back, *current;
369#endif
370
371#if defined(HAVE_ANDROID_PLATFORM) || defined (HAVE_OHOS_PLATFORM)
372   struct NativeWindow *window;
373   struct NativeWindowBuffer *buffer;
374
375   /* in-fence associated with buffer, -1 once passed down to dri layer: */
376   int in_fence_fd;
377
378   __DRIimage *dri_image_back;
379   __DRIimage *dri_image_front;
380
381   /* Used to record all the buffers created by ANativeWindow and their ages.
382    * Allocate number of color_buffers based on query to android bufferqueue
383    * and save color_buffers_count.
384    */
385   int color_buffers_count;
386   struct {
387      struct NativeWindowBuffer *buffer;
388      int age;
389   } *color_buffers, *back;
390   uint32_t gralloc_usage;
391#endif
392
393   /* surfaceless and device */
394   __DRIimage *front;
395   unsigned int visual;
396
397   int out_fence_fd;
398   EGLBoolean enable_out_fence;
399
400   /* swrast device */
401   char *swrast_device_buffer;
402};
403
404struct dri2_egl_config
405{
406   _EGLConfig base;
407   const __DRIconfig *dri_config[2][2];
408};
409
410struct dri2_egl_image
411{
412   _EGLImage base;
413   __DRIimage *dri_image;
414};
415
416struct dri2_egl_sync {
417   _EGLSync base;
418   mtx_t mutex;
419   cnd_t cond;
420   int refcount;
421   void *fence;
422};
423
424/* standard typecasts */
425_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
426_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
427_EGL_DRIVER_TYPECAST(dri2_egl_sync, _EGLSync, obj)
428
429extern const __DRIimageLookupExtension image_lookup_extension;
430extern const __DRIuseInvalidateExtension use_invalidate;
431extern const __DRIbackgroundCallableExtension background_callable_extension;
432extern const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension;
433
434EGLBoolean
435dri2_load_driver(_EGLDisplay *disp);
436
437/* Helper for platforms not using dri2_create_screen */
438void
439dri2_setup_screen(_EGLDisplay *disp);
440
441void
442dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval);
443
444EGLBoolean
445dri2_load_driver_swrast(_EGLDisplay *disp);
446
447EGLBoolean
448dri2_load_driver_dri3(_EGLDisplay *disp);
449
450EGLBoolean
451dri2_create_screen(_EGLDisplay *disp);
452
453EGLBoolean
454dri2_setup_extensions(_EGLDisplay *disp);
455
456__DRIdrawable *
457dri2_surface_get_dri_drawable(_EGLSurface *surf);
458
459GLboolean
460dri2_validate_egl_image(void *image, void *data);
461
462__DRIimage *
463dri2_lookup_egl_image_validated(void *image, void *data);
464
465__DRIimage *
466dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data);
467
468void
469dri2_get_shifts_and_sizes(const __DRIcoreExtension *core,
470		          const __DRIconfig *config, int *shifts,
471			  unsigned int *sizes);
472
473void
474dri2_get_render_type_float(const __DRIcoreExtension *core,
475                           const __DRIconfig *config,
476                           bool *is_float);
477
478unsigned int
479dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy,
480                                     const __DRIconfig *config);
481
482struct dri2_egl_config *
483dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
484                EGLint surface_type, const EGLint *attr_list,
485                const int *rgba_shifts, const unsigned int *rgba_sizes);
486
487EGLBoolean
488dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp);
489
490_EGLImage *
491dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
492                      EGLClientBuffer buffer, const EGLint *attr_list);
493
494_EGLImage *
495dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx,
496                          EGLClientBuffer buffer, const EGLint *attr_list);
497
498_EGLImage *
499dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image);
500
501#ifdef HAVE_X11_PLATFORM
502EGLBoolean
503dri2_initialize_x11(_EGLDisplay *disp);
504void
505dri2_teardown_x11(struct dri2_egl_display *dri2_dpy);
506unsigned int
507dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth);
508#else
509static inline EGLBoolean
510dri2_initialize_x11(_EGLDisplay *disp)
511{
512   return _eglError(EGL_NOT_INITIALIZED, "X11 platform not built");
513}
514static inline void
515dri2_teardown_x11(struct dri2_egl_display *dri2_dpy) {}
516static inline unsigned int
517dri2_x11_get_red_mask_for_depth(struct dri2_egl_display *dri2_dpy, int depth)
518{
519   return 0;
520}
521#endif
522
523#ifdef HAVE_DRM_PLATFORM
524EGLBoolean
525dri2_initialize_drm(_EGLDisplay *disp);
526void
527dri2_teardown_drm(struct dri2_egl_display *dri2_dpy);
528#else
529static inline EGLBoolean
530dri2_initialize_drm(_EGLDisplay *disp)
531{
532   return _eglError(EGL_NOT_INITIALIZED, "GBM/DRM platform not built");
533}
534static inline void
535dri2_teardown_drm(struct dri2_egl_display *dri2_dpy) {}
536#endif
537
538#ifdef HAVE_WAYLAND_PLATFORM
539EGLBoolean
540dri2_initialize_wayland(_EGLDisplay *disp);
541void
542dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy);
543bool
544dri2_wl_is_format_supported(void* user_data, uint32_t format);
545#else
546static inline EGLBoolean
547dri2_initialize_wayland(_EGLDisplay *disp)
548{
549   return _eglError(EGL_NOT_INITIALIZED, "Wayland platform not built");
550}
551static inline void
552dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy) {}
553#endif
554
555#ifdef HAVE_ANDROID_PLATFORM
556EGLBoolean
557dri2_initialize_android(_EGLDisplay *disp);
558#else
559static inline EGLBoolean
560dri2_initialize_android(_EGLDisplay *disp)
561{
562   return _eglError(EGL_NOT_INITIALIZED, "Android platform not built");
563}
564#endif
565
566#ifdef HAVE_OHOS_PLATFORM
567EGLBoolean
568dri2_initialize_ohos(_EGLDisplay *disp);
569#else
570static inline EGLBoolean
571dri2_initialize_ohos(_EGLDisplay *disp)
572{
573   return _eglError(EGL_NOT_INITIALIZED, "ohos platform not built");
574}
575#endif
576
577EGLBoolean
578dri2_initialize_surfaceless(_EGLDisplay *disp);
579
580EGLBoolean
581dri2_initialize_device(_EGLDisplay *disp);
582static inline void
583dri2_teardown_device(struct dri2_egl_display *dri2_dpy) { /* noop */ }
584
585void
586dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw);
587
588const __DRIconfig *
589dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type,
590                    EGLenum colorspace);
591
592static inline void
593dri2_set_WL_bind_wayland_display(_EGLDisplay *disp)
594{
595#ifdef HAVE_WAYLAND_PLATFORM
596   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
597
598   if (dri2_dpy->device_name && dri2_dpy->image) {
599       if (dri2_dpy->image->base.version >= 10 &&
600           dri2_dpy->image->getCapabilities != NULL) {
601           int capabilities;
602
603           capabilities =
604               dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen);
605           disp->Extensions.WL_bind_wayland_display =
606               (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0;
607       } else {
608           disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
609       }
610   }
611#endif
612}
613
614void
615dri2_display_destroy(_EGLDisplay *disp);
616
617__DRIbuffer *
618dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf,
619                                    unsigned int att, unsigned int format);
620
621void
622dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf);
623
624EGLBoolean
625dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
626        _EGLConfig *conf, const EGLint *attrib_list,
627        EGLBoolean enable_out_fence, void *native_surface);
628
629void
630dri2_fini_surface(_EGLSurface *surf);
631
632EGLBoolean
633dri2_create_drawable(struct dri2_egl_display *dri2_dpy,
634                     const __DRIconfig *config,
635                     struct dri2_egl_surface *dri2_surf,
636                     void *loaderPrivate);
637
638static inline uint64_t
639combine_u32_into_u64(uint32_t hi, uint32_t lo)
640{
641   return (((uint64_t) hi) << 32) | (((uint64_t) lo) & 0xffffffff);
642}
643
644#endif /* EGL_DRI2_INCLUDED */
645