2 * Mesa 3-D graphics library
5 * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com>
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.
26 #include "util/u_memory.h"
27 #include "util/u_inlines.h"
29 #include "pipe/p_compiler.h"
30 #include "pipe/p_screen.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "state_tracker/drm_driver.h"
38 #include "native_wayland.h"
40 #include <wayland-client.h>
41 #include "wayland-drm-client-protocol.h"
42 #include "wayland-egl-priv.h"
44 #include "common/native_wayland_drm_bufmgr_helper.h"
47 #include <sys/types.h>
51 struct wayland_drm_display
{
52 struct wayland_display base
;
54 const struct native_event_handler
*event_handler
;
56 struct wl_drm
*wl_drm
;
57 struct wl_drm
*wl_server_drm
; /* for EGL_WL_bind_wayland_display */
60 boolean authenticated
;
63 static INLINE
struct wayland_drm_display
*
64 wayland_drm_display(const struct native_display
*ndpy
)
66 return (struct wayland_drm_display
*) ndpy
;
70 wayland_drm_display_destroy(struct native_display
*ndpy
)
72 struct wayland_drm_display
*drmdpy
= wayland_drm_display(ndpy
);
77 wl_drm_destroy(drmdpy
->wl_drm
);
78 if (drmdpy
->device_name
)
79 FREE(drmdpy
->device_name
);
80 if (drmdpy
->base
.configs
)
81 FREE(drmdpy
->base
.configs
);
82 if (drmdpy
->base
.own_dpy
)
83 wl_display_destroy(drmdpy
->base
.dpy
);
90 static struct wl_buffer
*
91 wayland_create_drm_buffer(struct wayland_display
*display
,
92 struct wayland_surface
*surface
,
93 enum native_attachment attachment
)
95 struct wayland_drm_display
*drmdpy
= (struct wayland_drm_display
*) display
;
96 struct pipe_screen
*screen
= drmdpy
->base
.base
.screen
;
97 struct pipe_resource
*resource
;
98 struct winsys_handle wsh
;
100 enum wl_drm_format format
;
102 resource
= resource_surface_get_single_resource(surface
->rsurf
, attachment
);
103 resource_surface_get_size(surface
->rsurf
, &width
, &height
);
105 wsh
.type
= DRM_API_HANDLE_TYPE_SHARED
;
106 screen
->resource_get_handle(screen
, resource
, &wsh
);
108 pipe_resource_reference(&resource
, NULL
);
110 switch (surface
->color_format
) {
111 case PIPE_FORMAT_B8G8R8A8_UNORM
:
112 format
= WL_DRM_FORMAT_ARGB8888
;
114 case PIPE_FORMAT_B8G8R8X8_UNORM
:
115 format
= WL_DRM_FORMAT_XRGB8888
;
122 return wl_drm_create_buffer(drmdpy
->wl_drm
, wsh
.handle
,
123 width
, height
, wsh
.stride
, format
);
127 drm_handle_device(void *data
, struct wl_drm
*drm
, const char *device
)
129 struct wayland_drm_display
*drmdpy
= data
;
132 drmdpy
->device_name
= strdup(device
);
133 if (!drmdpy
->device_name
)
136 drmdpy
->fd
= open(drmdpy
->device_name
, O_RDWR
);
137 if (drmdpy
->fd
== -1) {
138 _eglLog(_EGL_WARNING
, "wayland-egl: could not open %s (%s)",
139 drmdpy
->device_name
, strerror(errno
));
143 drmGetMagic(drmdpy
->fd
, &magic
);
144 wl_drm_authenticate(drmdpy
->wl_drm
, magic
);
148 drm_handle_format(void *data
, struct wl_drm
*drm
, uint32_t format
)
150 struct wayland_drm_display
*drmdpy
= data
;
153 case WL_DRM_FORMAT_ARGB8888
:
154 drmdpy
->base
.formats
|= HAS_ARGB8888
;
156 case WL_DRM_FORMAT_XRGB8888
:
157 drmdpy
->base
.formats
|= HAS_XRGB8888
;
163 drm_handle_authenticated(void *data
, struct wl_drm
*drm
)
165 struct wayland_drm_display
*drmdpy
= data
;
167 drmdpy
->authenticated
= true;
170 static const struct wl_drm_listener drm_listener
= {
173 drm_handle_authenticated
177 wayland_drm_display_init_screen(struct native_display
*ndpy
)
179 struct wayland_drm_display
*drmdpy
= wayland_drm_display(ndpy
);
182 id
= wl_display_get_global(drmdpy
->base
.dpy
, "wl_drm", 1);
184 wl_display_roundtrip(drmdpy
->base
.dpy
);
185 id
= wl_display_get_global(drmdpy
->base
.dpy
, "wl_drm", 1);
189 drmdpy
->wl_drm
= wl_display_bind(drmdpy
->base
.dpy
, id
, &wl_drm_interface
);
193 wl_drm_add_listener(drmdpy
->wl_drm
, &drm_listener
, drmdpy
);
194 wl_display_roundtrip(drmdpy
->base
.dpy
);
195 if (drmdpy
->fd
== -1)
198 wl_display_roundtrip(drmdpy
->base
.dpy
);
199 if (!drmdpy
->authenticated
)
202 if (drmdpy
->base
.formats
== 0)
203 wl_display_roundtrip(drmdpy
->base
.dpy
);
204 if (drmdpy
->base
.formats
== 0)
207 drmdpy
->base
.base
.screen
=
208 drmdpy
->event_handler
->new_drm_screen(&drmdpy
->base
.base
,
210 if (!drmdpy
->base
.base
.screen
) {
211 _eglLog(_EGL_WARNING
, "failed to create DRM screen");
218 static struct native_display_buffer wayland_drm_display_buffer
= {
219 /* use the helpers */
220 drm_display_import_native_buffer
,
221 drm_display_export_native_buffer
225 wayland_drm_display_authenticate(void *user_data
, uint32_t magic
)
227 struct native_display
*ndpy
= user_data
;
228 struct wayland_drm_display
*drmdpy
= wayland_drm_display(ndpy
);
229 boolean current_authenticate
, authenticated
;
231 current_authenticate
= drmdpy
->authenticated
;
233 wl_drm_authenticate(drmdpy
->wl_drm
, magic
);
234 wl_display_roundtrip(drmdpy
->base
.dpy
);
235 authenticated
= drmdpy
->authenticated
;
237 drmdpy
->authenticated
= current_authenticate
;
239 return authenticated
? 0 : -1;
242 static struct wayland_drm_callbacks wl_drm_callbacks
= {
243 wayland_drm_display_authenticate
,
244 egl_g3d_wl_drm_helper_reference_buffer
,
245 egl_g3d_wl_drm_helper_unreference_buffer
249 wayland_drm_display_bind_wayland_display(struct native_display
*ndpy
,
250 struct wl_display
*wl_dpy
)
252 struct wayland_drm_display
*drmdpy
= wayland_drm_display(ndpy
);
254 if (drmdpy
->wl_server_drm
)
257 drmdpy
->wl_server_drm
=
258 wayland_drm_init(wl_dpy
, drmdpy
->device_name
,
259 &wl_drm_callbacks
, ndpy
);
261 if (!drmdpy
->wl_server_drm
)
268 wayland_drm_display_unbind_wayland_display(struct native_display
*ndpy
,
269 struct wl_display
*wl_dpy
)
271 struct wayland_drm_display
*drmdpy
= wayland_drm_display(ndpy
);
273 if (!drmdpy
->wl_server_drm
)
276 wayland_drm_uninit(drmdpy
->wl_server_drm
);
277 drmdpy
->wl_server_drm
= NULL
;
282 static struct native_display_wayland_bufmgr wayland_drm_display_wayland_bufmgr
= {
283 wayland_drm_display_bind_wayland_display
,
284 wayland_drm_display_unbind_wayland_display
,
285 egl_g3d_wl_drm_common_wl_buffer_get_resource
289 struct wayland_display
*
290 wayland_create_drm_display(struct wl_display
*dpy
,
291 const struct native_event_handler
*event_handler
)
293 struct wayland_drm_display
*drmdpy
;
295 drmdpy
= CALLOC_STRUCT(wayland_drm_display
);
299 drmdpy
->event_handler
= event_handler
;
301 drmdpy
->base
.dpy
= dpy
;
302 if (!drmdpy
->base
.dpy
) {
303 wayland_drm_display_destroy(&drmdpy
->base
.base
);
307 drmdpy
->base
.base
.init_screen
= wayland_drm_display_init_screen
;
308 drmdpy
->base
.base
.destroy
= wayland_drm_display_destroy
;
309 drmdpy
->base
.base
.buffer
= &wayland_drm_display_buffer
;
310 drmdpy
->base
.base
.wayland_bufmgr
= &wayland_drm_display_wayland_bufmgr
;
312 drmdpy
->base
.create_buffer
= wayland_create_drm_buffer
;
314 return &drmdpy
->base
;
317 /* vim: set sw=3 ts=8 sts=3 expandtab: */