• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* TODO */
2 
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #include <vulkan/vulkan.h>
7 
8 #include "dri_util.h"
9 #include "egl_dri2.h"
10 #include "kopper_interface.h"
11 
12 #include "display_type.h"
13 #include "external_window.h"
14 
15 static _EGLSurface *
ohos_create_surface(_EGLDisplay * disp,EGLint type,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)16 ohos_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
17                     void *native_window, const EGLint *attrib_list)
18 {
19    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
20    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
21    struct dri2_egl_surface *dri2_surf;
22    struct NativeWindow *window = native_window;
23    const struct dri_config *config;
24 
25    dri2_surf = calloc(1, sizeof *dri2_surf);
26    if (!dri2_surf) {
27       _eglError(EGL_BAD_ALLOC, "ohos_create_surface");
28       return NULL;
29    }
30 
31    if (!dri2_init_surface(&dri2_surf->base, disp, type, conf, attrib_list,
32                           false, native_window))
33       goto cleanup_surface;
34 
35    if (type == EGL_WINDOW_BIT) {
36       int format = 0;
37 
38       OH_NativeWindow_NativeWindowHandleOpt(native_window, GET_FORMAT, &format);
39       if (format < 0) {
40          _eglError(EGL_BAD_NATIVE_WINDOW, "ohos_create_surface");
41          goto cleanup_surface;
42       }
43 
44       if (format != dri2_conf->base.NativeVisualID) {
45          _eglLog(_EGL_WARNING, "Native format mismatch: 0x%x != 0x%x", format,
46                  dri2_conf->base.NativeVisualID);
47       }
48 
49       OH_NativeWindow_NativeWindowHandleOpt(native_window, GET_BUFFER_GEOMETRY,
50                                             &dri2_surf->base.Height,
51                                             &dri2_surf->base.Width);
52 
53       dri2_surf->window = window;
54    }
55 
56    config = dri2_get_dri_config(dri2_conf, type, dri2_surf->base.GLColorspace);
57    if (!config) {
58       _eglError(EGL_BAD_MATCH,
59                 "Unsupported surfacetype/colorspace configuration");
60       goto cleanup_surface;
61    }
62 
63    if (!dri2_create_drawable(dri2_dpy, config, dri2_surf, dri2_surf))
64       goto cleanup_surface;
65 
66    if (window)
67       OH_NativeWindow_NativeObjectReference(window);
68 
69    return &dri2_surf->base;
70 
71 cleanup_surface:
72    free(dri2_surf);
73    return NULL;
74 }
75 
76 static EGLBoolean
device_destroy_surface(_EGLDisplay * disp,_EGLSurface * surf)77 device_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
78 {
79    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf);
80 
81    driDestroyDrawable(dri2_surf->dri_drawable);
82 
83    if (dri2_surf->window)
84       OH_NativeWindow_NativeObjectUnreference(dri2_surf->window);
85 
86    dri2_fini_surface(surf);
87    free(dri2_surf);
88    return EGL_TRUE;
89 }
90 
91 static _EGLSurface *
ohos_create_window_surface(_EGLDisplay * disp,_EGLConfig * conf,void * native_window,const EGLint * attrib_list)92 ohos_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
93                            void *native_window, const EGLint *attrib_list)
94 {
95    return ohos_create_surface(disp, EGL_WINDOW_BIT, conf, native_window,
96                               attrib_list);
97 }
98 
99 static _EGLSurface *
ohos_create_pbuffer_surface(_EGLDisplay * disp,_EGLConfig * conf,const EGLint * attrib_list)100 ohos_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
101                             const EGLint *attrib_list)
102 {
103    return ohos_create_surface(disp, EGL_PBUFFER_BIT, conf, NULL, attrib_list);
104 }
105 
106 static EGLBoolean
ohos_swap_buffers(_EGLDisplay * disp,_EGLSurface * draw)107 ohos_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
108 {
109    struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
110 
111    driSwapBuffers(dri2_surf->dri_drawable);
112 
113    return EGL_TRUE;
114 }
115 
116 static const struct dri2_egl_display_vtbl dri2_ohos_display_vtbl = {
117    .create_window_surface = ohos_create_window_surface,
118    .create_pbuffer_surface = ohos_create_pbuffer_surface,
119    .destroy_surface = device_destroy_surface,
120    .create_image = dri2_create_image_khr,
121    .get_dri_drawable = dri2_surface_get_dri_drawable,
122    .swap_buffers = ohos_swap_buffers,
123 };
124 
125 static void
kopperSetSurfaceCreateInfo(void * _draw,struct kopper_loader_info * out)126 kopperSetSurfaceCreateInfo(void *_draw, struct kopper_loader_info *out)
127 {
128    struct dri2_egl_surface *dri2_surf = _draw;
129    VkSurfaceCreateInfoOHOS *sci = (VkSurfaceCreateInfoOHOS *)&out->bos;
130 
131    sci->sType = VK_STRUCTURE_TYPE_SURFACE_CREATE_INFO_OHOS;
132    sci->pNext = NULL;
133    sci->flags = 0;
134    sci->window = dri2_surf->window;
135 
136    out->present_opaque = dri2_surf->base.PresentOpaque;
137    /* convert to vulkan constants */
138    switch (dri2_surf->base.CompressionRate) {
139    case EGL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT:
140       out->compression = 0;
141       break;
142    case EGL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT:
143       out->compression = UINT32_MAX;
144       break;
145 #define EGL_VK_COMP(NUM)                                                       \
146    case EGL_SURFACE_COMPRESSION_FIXED_RATE_##NUM##BPC_EXT:                     \
147       out->compression = VK_IMAGE_COMPRESSION_FIXED_RATE_##NUM##BPC_BIT_EXT;   \
148       break
149       EGL_VK_COMP(1);
150       EGL_VK_COMP(2);
151       EGL_VK_COMP(3);
152       EGL_VK_COMP(4);
153       EGL_VK_COMP(5);
154       EGL_VK_COMP(6);
155       EGL_VK_COMP(7);
156       EGL_VK_COMP(8);
157       EGL_VK_COMP(9);
158       EGL_VK_COMP(10);
159       EGL_VK_COMP(11);
160       EGL_VK_COMP(12);
161 #undef EGL_VK_COMP
162    default:
163       unreachable("unknown compression rate");
164    }
165 }
166 
167 static const __DRIkopperLoaderExtension kopper_loader_extension = {
168    .base = {__DRI_KOPPER_LOADER, 1},
169    .SetSurfaceCreateInfo = kopperSetSurfaceCreateInfo,
170 };
171 
172 static void
ohos_drawable_info(struct dri_drawable * draw,int * x,int * y,int * w,int * h,void * loaderPrivate)173 ohos_drawable_info(struct dri_drawable *draw, int *x, int *y, int *w, int *h,
174                    void *loaderPrivate)
175 {
176    struct dri2_egl_surface *dri2_surf = loaderPrivate;
177 
178    *x = *y = 0;
179    *w = dri2_surf->base.Width;
180    *h = dri2_surf->base.Height;
181 }
182 
183 static const __DRIswrastLoaderExtension swrast_loader_extension = {
184    .base = {__DRI_SWRAST_LOADER, 1},
185    .getDrawableInfo = ohos_drawable_info,
186 };
187 
188 static unsigned
ohos_get_capability(void * loaderPrivate,enum dri_loader_cap cap)189 ohos_get_capability(void *loaderPrivate, enum dri_loader_cap cap)
190 {
191    /* Note: loaderPrivate is _EGLDisplay* */
192    switch (cap) {
193    case DRI_LOADER_CAP_RGBA_ORDERING:
194       return 1;
195    default:
196       return 0;
197    }
198 }
199 
200 static const __DRIdri2LoaderExtension dri2_loader_extension = {
201    .base = {__DRI_DRI2_LOADER, 4},
202    .getCapability = ohos_get_capability,
203 };
204 
205 static const __DRIextension *image_loader_extensions[] = {
206    &image_lookup_extension.base,
207    &kopper_loader_extension.base,
208    &swrast_loader_extension.base,
209    &dri2_loader_extension.base,
210    NULL,
211 };
212 
213 static bool
load_zink_kopper(_EGLDisplay * disp)214 load_zink_kopper(_EGLDisplay *disp)
215 {
216    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
217 
218    dri2_dpy->fd_render_gpu = -1;
219    dri2_dpy->fd_display_gpu = -1;
220    dri2_dpy->driver_name = strdup("zink");
221    if (!dri2_dpy->driver_name)
222       return false;
223 
224    if (!dri2_load_driver(disp)) {
225       free(dri2_dpy->driver_name);
226       dri2_dpy->driver_name = NULL;
227       return false;
228    }
229 
230    dri2_dpy->loader_extensions = image_loader_extensions;
231 
232    return true;
233 }
234 
235 static void
ohos_add_configs_for_visuals(_EGLDisplay * disp)236 ohos_add_configs_for_visuals(_EGLDisplay *disp)
237 {
238    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
239    static const struct {
240       int hal_format;
241       enum pipe_format pipe_format;
242    } visuals[] = {
243       {PIXEL_FMT_RGBA_8888, PIPE_FORMAT_RGBA8888_UNORM},
244       {PIXEL_FMT_RGBX_8888, PIPE_FORMAT_BGRX8888_UNORM},
245       {PIXEL_FMT_RGB_565, PIPE_FORMAT_B5G6R5_UNORM},
246       /* This must be after HAL_PIXEL_FMT_RGBA_8888, we only keep BGRA
247        * visual if it turns out RGBA visual is not available.
248        */
249       {PIXEL_FMT_BGRA_8888, PIPE_FORMAT_BGRA8888_UNORM},
250    };
251 
252    unsigned int format_count[ARRAY_SIZE(visuals)] = {0};
253 
254    bool has_rgba = false;
255    for (int i = 0; i < ARRAY_SIZE(visuals); i++) {
256       if (visuals[i].hal_format == PIXEL_FMT_BGRA_8888 && has_rgba)
257          continue;
258       for (int j = 0; dri2_dpy->driver_configs[j]; j++) {
259          const struct gl_config *gl_config =
260             (struct gl_config *)dri2_dpy->driver_configs[j];
261 
262          /* Rather than have duplicate table entries for _SRGB formats, just
263           * use the linear version of the format for the comparision:
264           */
265          enum pipe_format linear_format =
266             util_format_linear(gl_config->color_format);
267          if (linear_format != visuals[i].pipe_format)
268             continue;
269 
270          const EGLint surface_type = EGL_WINDOW_BIT | EGL_PBUFFER_BIT;
271          const EGLint config_attrs[] = {
272             EGL_NATIVE_VISUAL_ID, visuals[i].hal_format, EGL_NATIVE_VISUAL_TYPE,
273             visuals[i].hal_format, EGL_NONE};
274 
275          _eglLog(_EGL_DEBUG, "calling dri2_add_config for %x",
276                  visuals[i].hal_format);
277          struct dri2_egl_config *dri2_conf = dri2_add_config(
278             disp, dri2_dpy->driver_configs[j], surface_type, config_attrs);
279          if (dri2_conf)
280             format_count[i]++;
281       }
282 
283       if (visuals[i].hal_format == PIXEL_FMT_RGBA_8888 && format_count[i])
284          has_rgba = true;
285    }
286 
287    for (int i = 0; i < ARRAY_SIZE(format_count); i++) {
288       if (!format_count[i]) {
289          _eglLog(_EGL_DEBUG, "No DRI config supports native format 0x%x",
290                  visuals[i].hal_format);
291       }
292    }
293 }
294 
295 EGLBoolean
dri2_initialize_ohos(_EGLDisplay * disp)296 dri2_initialize_ohos(_EGLDisplay *disp)
297 {
298    const char *err;
299    struct dri2_egl_display *dri2_dpy = dri2_display_create(disp);
300    if (!dri2_dpy)
301       return EGL_FALSE;
302 
303    err = "DRI2: failed to load driver";
304    if (!load_zink_kopper(disp))
305       goto cleanup;
306 
307    if (!dri2_create_screen(disp)) {
308       err = "DRI2: failed to create screen";
309       goto cleanup;
310    }
311 
312    dri2_setup_screen(disp);
313 
314    /* Create configs *after* enabling extensions because presence of DRI
315     * driver extensions can affect the capabilities of EGLConfigs.
316     */
317    ohos_add_configs_for_visuals(disp);
318 
319    disp->Extensions.KHR_image = EGL_TRUE;
320 
321    /* Fill vtbl last to prevent accidentally calling virtual function during
322     * initialization.
323     */
324    dri2_dpy->vtbl = &dri2_ohos_display_vtbl;
325 
326    return EGL_TRUE;
327 
328 cleanup:
329    dri2_display_destroy(disp);
330    return _eglError(EGL_NOT_INITIALIZED, err);
331 }
332