2 * Mesa 3-D graphics library
4 * Copyright (c) 2014 The Chromium OS Authors.
5 * Copyright © 2011 Intel Corporation
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
31 #include <sys/types.h>
40 surfaceless_alloc_image(struct dri2_egl_display
*dri2_dpy
,
41 struct dri2_egl_surface
*dri2_surf
)
43 return dri2_dpy
->image
->createImage(
45 dri2_surf
->base
.Width
,
46 dri2_surf
->base
.Height
,
53 surfaceless_free_images(struct dri2_egl_surface
*dri2_surf
)
55 struct dri2_egl_display
*dri2_dpy
=
56 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
58 if (dri2_surf
->front
) {
59 dri2_dpy
->image
->destroyImage(dri2_surf
->front
);
60 dri2_surf
->front
= NULL
;
63 free(dri2_surf
->swrast_device_buffer
);
64 dri2_surf
->swrast_device_buffer
= NULL
;
68 surfaceless_image_get_buffers(__DRIdrawable
*driDrawable
,
73 struct __DRIimageList
*buffers
)
75 struct dri2_egl_surface
*dri2_surf
= loaderPrivate
;
76 struct dri2_egl_display
*dri2_dpy
=
77 dri2_egl_display(dri2_surf
->base
.Resource
.Display
);
79 buffers
->image_mask
= 0;
80 buffers
->front
= NULL
;
83 /* The EGL 1.5 spec states that pbuffers are single-buffered. Specifically,
84 * the spec states that they have a back buffer but no front buffer, in
85 * contrast to pixmaps, which have a front buffer but no back buffer.
87 * Single-buffered surfaces with no front buffer confuse Mesa; so we deviate
88 * from the spec, following the precedent of Mesa's EGL X11 platform. The
89 * X11 platform correctly assigns pbuffers to single-buffered configs, but
90 * assigns the pbuffer a front buffer instead of a back buffer.
92 * Pbuffers in the X11 platform mostly work today, so let's just copy its
93 * behavior instead of trying to fix (and hence potentially breaking) the
97 if (buffer_mask
& __DRI_IMAGE_BUFFER_FRONT
) {
99 if (!dri2_surf
->front
)
101 surfaceless_alloc_image(dri2_dpy
, dri2_surf
);
103 buffers
->image_mask
|= __DRI_IMAGE_BUFFER_FRONT
;
104 buffers
->front
= dri2_surf
->front
;
111 dri2_surfaceless_create_surface(_EGLDisplay
*disp
, EGLint type
,
112 _EGLConfig
*conf
, const EGLint
*attrib_list
)
114 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
115 struct dri2_egl_config
*dri2_conf
= dri2_egl_config(conf
);
116 struct dri2_egl_surface
*dri2_surf
;
117 const __DRIconfig
*config
;
119 /* Make sure to calloc so all pointers
120 * are originally NULL.
122 dri2_surf
= calloc(1, sizeof *dri2_surf
);
125 _eglError(EGL_BAD_ALLOC
, "eglCreatePbufferSurface");
129 if (!dri2_init_surface(&dri2_surf
->base
, disp
, type
, conf
, attrib_list
,
131 goto cleanup_surface
;
133 config
= dri2_get_dri_config(dri2_conf
, type
,
134 dri2_surf
->base
.GLColorspace
);
137 _eglError(EGL_BAD_MATCH
, "Unsupported surfacetype/colorspace configuration");
138 goto cleanup_surface
;
141 dri2_surf
->visual
= dri2_image_format_for_pbuffer_config(dri2_dpy
, config
);
142 if (dri2_surf
->visual
== __DRI_IMAGE_FORMAT_NONE
)
143 goto cleanup_surface
;
145 if (!dri2_create_drawable(dri2_dpy
, config
, dri2_surf
, dri2_surf
))
146 goto cleanup_surface
;
148 return &dri2_surf
->base
;
156 surfaceless_destroy_surface(_EGLDisplay
*disp
, _EGLSurface
*surf
)
158 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
159 struct dri2_egl_surface
*dri2_surf
= dri2_egl_surface(surf
);
161 surfaceless_free_images(dri2_surf
);
163 dri2_dpy
->core
->destroyDrawable(dri2_surf
->dri_drawable
);
165 dri2_fini_surface(surf
);
171 dri2_surfaceless_create_pbuffer_surface(_EGLDisplay
*disp
, _EGLConfig
*conf
,
172 const EGLint
*attrib_list
)
174 return dri2_surfaceless_create_surface(disp
, EGL_PBUFFER_BIT
, conf
,
178 static const struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl
= {
179 .create_pbuffer_surface
= dri2_surfaceless_create_pbuffer_surface
,
180 .destroy_surface
= surfaceless_destroy_surface
,
181 .create_image
= dri2_create_image_khr
,
182 .get_dri_drawable
= dri2_surface_get_dri_drawable
,
186 surfaceless_flush_front_buffer(__DRIdrawable
*driDrawable
, void *loaderPrivate
)
191 surfaceless_get_capability(void *loaderPrivate
, enum dri_loader_cap cap
)
193 /* Note: loaderPrivate is _EGLDisplay* */
195 case DRI_LOADER_CAP_FP16
:
202 static const __DRIimageLoaderExtension image_loader_extension
= {
203 .base
= { __DRI_IMAGE_LOADER
, 2 },
204 .getBuffers
= surfaceless_image_get_buffers
,
205 .flushFrontBuffer
= surfaceless_flush_front_buffer
,
206 .getCapability
= surfaceless_get_capability
,
209 static const __DRIextension
*image_loader_extensions
[] = {
210 &image_loader_extension
.base
,
211 &image_lookup_extension
.base
,
212 &use_invalidate
.base
,
216 static const __DRIextension
*swrast_loader_extensions
[] = {
217 &swrast_pbuffer_loader_extension
.base
,
218 &image_loader_extension
.base
,
219 &image_lookup_extension
.base
,
220 &use_invalidate
.base
,
225 surfaceless_probe_device(_EGLDisplay
*disp
, bool swrast
)
227 #define MAX_DRM_DEVICES 64
228 const unsigned node_type
= swrast
? DRM_NODE_PRIMARY
: DRM_NODE_RENDER
;
229 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
230 drmDevicePtr device
, devices
[MAX_DRM_DEVICES
] = { NULL
};
233 num_devices
= drmGetDevices2(0, devices
, ARRAY_SIZE(devices
));
237 for (i
= 0; i
< num_devices
; ++i
) {
240 if (!(device
->available_nodes
& (1 << node_type
)))
243 dri2_dpy
->fd
= loader_open_device(device
->nodes
[node_type
]);
244 if (dri2_dpy
->fd
< 0)
247 disp
->Device
= _eglAddDevice(dri2_dpy
->fd
, swrast
);
254 char *driver_name
= loader_get_driver_for_fd(dri2_dpy
->fd
);
256 /* Use kms swrast only with vgem / virtio_gpu.
257 * virtio-gpu fallbacks to software rendering when 3D features
258 * are unavailable since 6c5ab, and kms_swrast is more
259 * feature complete than swrast.
262 (strcmp(driver_name
, "vgem") == 0 ||
263 strcmp(driver_name
, "virtio_gpu") == 0))
264 dri2_dpy
->driver_name
= strdup("kms_swrast");
267 /* Use the given hardware driver */
268 dri2_dpy
->driver_name
= driver_name
;
271 if (dri2_dpy
->driver_name
&& dri2_load_driver_dri3(disp
))
274 free(dri2_dpy
->driver_name
);
275 dri2_dpy
->driver_name
= NULL
;
279 drmFreeDevices(devices
, num_devices
);
281 if (i
== num_devices
)
285 dri2_dpy
->loader_extensions
= swrast_loader_extensions
;
287 dri2_dpy
->loader_extensions
= image_loader_extensions
;
293 surfaceless_probe_device_sw(_EGLDisplay
*disp
)
295 struct dri2_egl_display
*dri2_dpy
= dri2_egl_display(disp
);
298 disp
->Device
= _eglAddDevice(dri2_dpy
->fd
, true);
299 assert(disp
->Device
);
301 dri2_dpy
->driver_name
= strdup("swrast");
302 if (!dri2_dpy
->driver_name
)
305 if (!dri2_load_driver_swrast(disp
)) {
306 free(dri2_dpy
->driver_name
);
307 dri2_dpy
->driver_name
= NULL
;
311 dri2_dpy
->loader_extensions
= swrast_loader_extensions
;
316 dri2_initialize_surfaceless(_EGLDisplay
*disp
)
318 struct dri2_egl_display
*dri2_dpy
;
320 bool driver_loaded
= false;
322 dri2_dpy
= calloc(1, sizeof *dri2_dpy
);
324 return _eglError(EGL_BAD_ALLOC
, "eglInitialize");
327 disp
->DriverData
= (void *) dri2_dpy
;
329 if (!disp
->Options
.ForceSoftware
) {
330 driver_loaded
= surfaceless_probe_device(disp
, false);
332 _eglLog(_EGL_WARNING
,
333 "No hardware driver found, falling back to software rendering");
337 driver_loaded
= surfaceless_probe_device(disp
, true);
339 if (!driver_loaded
) {
340 _eglLog(_EGL_DEBUG
, "Falling back to surfaceless swrast without DRM.");
341 if (!surfaceless_probe_device_sw(disp
)) {
342 err
= "DRI2: failed to load driver";
347 if (!dri2_create_screen(disp
)) {
348 err
= "DRI2: failed to create screen";
352 if (!dri2_setup_extensions(disp
)) {
353 err
= "DRI2: failed to find required DRI extensions";
357 dri2_setup_screen(disp
);
358 #ifdef HAVE_WAYLAND_PLATFORM
359 dri2_dpy
->device_name
= loader_get_device_name_for_fd(dri2_dpy
->fd
);
361 dri2_set_WL_bind_wayland_display(disp
);
363 if (!dri2_add_pbuffer_configs_for_visuals(disp
)) {
364 err
= "DRI2: failed to add configs";
368 /* Fill vtbl last to prevent accidentally calling virtual function during
371 dri2_dpy
->vtbl
= &dri2_surfaceless_display_vtbl
;
376 dri2_display_destroy(disp
);
377 return _eglError(EGL_NOT_INITIALIZED
, err
);