native_drm.c revision dc520d4fefa6a92b3a8f2eed3c5a1044dfccb3ff
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa 3-D graphics library 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: 7.11 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2011 Benjamin Franzke <benjaminfranzke@googlemail.com> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to deal in the Software without restriction, including without limitation 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions: 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) * The above copyright notice and this permission notice shall be included 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * in all copies or substantial portions of the Software. 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DEALINGS IN THE SOFTWARE. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "util/u_memory.h" 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "util/u_inlines.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "pipe/p_compiler.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_screen.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_context.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pipe/p_state.h" 331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "state_tracker/drm_driver.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "egllog.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "native_wayland.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* see get_drm_screen_name */ 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <radeon_drm.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "radeon/drm/radeon_drm_public.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wayland-client.h> 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "wayland-drm-client-protocol.h" 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "wayland-egl-priv.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <xf86drm.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct wayland_drm_display { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wayland_display base; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct native_event_handler *event_handler; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wl_drm *wl_drm; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char *device_name; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boolean authenticated; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static INLINE struct wayland_drm_display * 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wayland_drm_display(const struct native_display *ndpy) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (struct wayland_drm_display *) ndpy; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)sync_callback(void *data) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *done = data; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *done = 1; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)force_roundtrip(struct wl_display *display) 80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles){ 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int done = 0; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_sync_callback(display, sync_callback, &done); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_iterate(display, WL_DISPLAY_WRITABLE); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!done) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wl_display_iterate(display, WL_DISPLAY_READABLE); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wayland_drm_display_destroy(struct native_display *ndpy) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drmdpy->fd) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(drmdpy->fd); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drmdpy->wl_drm) 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) wl_drm_destroy(drmdpy->wl_drm); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drmdpy->device_name) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(drmdpy->device_name); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drmdpy->base.config) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(drmdpy->base.config); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ndpy_uninit(ndpy); 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FREE(drmdpy); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct wl_buffer * 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)wayland_create_drm_buffer(struct wayland_display *display, 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct wayland_surface *surface, 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum native_attachment attachment) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct wayland_drm_display *drmdpy = (struct wayland_drm_display *) display; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct pipe_screen *screen = drmdpy->base.base.screen; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct pipe_resource *resource; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct winsys_handle wsh; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint width, height; 1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct wl_visual *visual; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource = resource_surface_get_single_resource(surface->rsurf, attachment); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource_surface_get_size(surface->rsurf, &width, &height); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wsh.type = DRM_API_HANDLE_TYPE_SHARED; 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) screen->resource_get_handle(screen, resource, &wsh); 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_resource_reference(&resource, NULL); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (surface->type) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WL_WINDOW_SURFACE: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visual = surface->win->visual; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WL_PIXMAP_SURFACE: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visual = surface->pix->visual; 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return wl_drm_create_buffer(drmdpy->wl_drm, wsh.handle, 140 width, height, wsh.stride, visual); 141} 142 143static const char * 144get_drm_screen_name(int fd, drmVersionPtr version) 145{ 146 const char *name = version->name; 147 148 if (name && !strcmp(name, "radeon")) { 149 int chip_id; 150 struct drm_radeon_info info; 151 152 memset(&info, 0, sizeof(info)); 153 info.request = RADEON_INFO_DEVICE_ID; 154 info.value = pointer_to_intptr(&chip_id); 155 if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) 156 return NULL; 157 158 name = is_r3xx(chip_id) ? "r300" : "r600"; 159 } 160 161 return name; 162} 163 164static void 165drm_handle_device(void *data, struct wl_drm *drm, const char *device) 166{ 167 struct wayland_drm_display *drmdpy = data; 168 drm_magic_t magic; 169 170 drmdpy->device_name = strdup(device); 171 if (!drmdpy->device_name) 172 return; 173 174 drmdpy->fd = open(drmdpy->device_name, O_RDWR); 175 if (drmdpy->fd == -1) { 176 _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)", 177 drmdpy->device_name, strerror(errno)); 178 return; 179 } 180 181 drmGetMagic(drmdpy->fd, &magic); 182 wl_drm_authenticate(drmdpy->wl_drm, magic); 183} 184 185static void 186drm_handle_authenticated(void *data, struct wl_drm *drm) 187{ 188 struct wayland_drm_display *drmdpy = data; 189 190 drmdpy->authenticated = true; 191} 192 193static const struct wl_drm_listener drm_listener = { 194 drm_handle_device, 195 drm_handle_authenticated 196}; 197 198static boolean 199wayland_drm_display_init_screen(struct native_display *ndpy) 200{ 201 struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy); 202 drmVersionPtr version; 203 const char *driver_name; 204 uint32_t id; 205 206 id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1); 207 if (id == 0) 208 force_roundtrip(drmdpy->base.dpy); 209 id = wl_display_get_global(drmdpy->base.dpy, "wl_drm", 1); 210 if (id == 0) 211 return FALSE; 212 213 drmdpy->wl_drm = wl_drm_create(drmdpy->base.dpy, id, 1); 214 if (!drmdpy->wl_drm) 215 return FALSE; 216 217 wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy); 218 force_roundtrip(drmdpy->base.dpy); 219 if (drmdpy->fd == -1) 220 return FALSE; 221 222 force_roundtrip(drmdpy->base.dpy); 223 if (!drmdpy->authenticated) 224 return FALSE; 225 226 version = drmGetVersion(drmdpy->fd); 227 if (!version) { 228 _eglLog(_EGL_WARNING, "invalid fd %d", drmdpy->fd); 229 return FALSE; 230 } 231 232 /* FIXME: share this with native_drm or egl_dri2 */ 233 driver_name = get_drm_screen_name(drmdpy->fd, version); 234 235 drmdpy->base.base.screen = 236 drmdpy->event_handler->new_drm_screen(&drmdpy->base.base, 237 driver_name, drmdpy->fd); 238 drmFreeVersion(version); 239 240 if (!drmdpy->base.base.screen) { 241 _eglLog(_EGL_WARNING, "failed to create DRM screen"); 242 return FALSE; 243 } 244 245 return TRUE; 246} 247 248static struct pipe_resource * 249wayland_drm_display_import_buffer(struct native_display *ndpy, 250 const struct pipe_resource *templ, 251 void *buf) 252{ 253 return ndpy->screen->resource_from_handle(ndpy->screen, 254 templ, (struct winsys_handle *) buf); 255} 256 257static boolean 258wayland_drm_display_export_buffer(struct native_display *ndpy, 259 struct pipe_resource *res, 260 void *buf) 261{ 262 return ndpy->screen->resource_get_handle(ndpy->screen, 263 res, (struct winsys_handle *) buf); 264} 265 266static struct native_display_buffer wayland_drm_display_buffer = { 267 wayland_drm_display_import_buffer, 268 wayland_drm_display_export_buffer 269}; 270 271struct wayland_display * 272wayland_create_drm_display(struct wl_display *dpy, 273 struct native_event_handler *event_handler, 274 void *user_data) 275{ 276 struct wayland_drm_display *drmdpy; 277 278 drmdpy = CALLOC_STRUCT(wayland_drm_display); 279 if (!drmdpy) 280 return NULL; 281 282 drmdpy->event_handler = event_handler; 283 drmdpy->base.base.user_data = user_data; 284 285 drmdpy->base.dpy = dpy; 286 if (!drmdpy->base.dpy) { 287 wayland_drm_display_destroy(&drmdpy->base.base); 288 return NULL; 289 } 290 291 if (!wayland_drm_display_init_screen(&drmdpy->base.base)) { 292 wayland_drm_display_destroy(&drmdpy->base.base); 293 return NULL; 294 } 295 drmdpy->base.base.destroy = wayland_drm_display_destroy; 296 drmdpy->base.base.buffer = &wayland_drm_display_buffer; 297 298 drmdpy->base.create_buffer = wayland_create_drm_buffer; 299 300 return &drmdpy->base; 301} 302 303/* vim: set sw=3 ts=8 sts=3 expandtab: */ 304