native_drm.c revision e28ecdee0396cc6665f9be95cfbaa2c2db1d4891
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.8 4 * 5 * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org> 6 * 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: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 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. 24 */ 25 26#include <sys/types.h> 27#include <sys/stat.h> 28#include <fcntl.h> 29 30#include "util/u_memory.h" 31#include "egllog.h" 32 33#include "native_drm.h" 34 35/* see get_drm_screen_name */ 36#include <radeon_drm.h> 37#include "radeon/drm/radeon_drm_public.h" 38 39static boolean 40drm_display_is_format_supported(struct native_display *ndpy, 41 enum pipe_format fmt, boolean is_color) 42{ 43 return ndpy->screen->is_format_supported(ndpy->screen, 44 fmt, PIPE_TEXTURE_2D, 0, 45 (is_color) ? PIPE_BIND_RENDER_TARGET : 46 PIPE_BIND_DEPTH_STENCIL, 0); 47} 48 49static const struct native_config ** 50drm_display_get_configs(struct native_display *ndpy, int *num_configs) 51{ 52 struct drm_display *drmdpy = drm_display(ndpy); 53 const struct native_config **configs; 54 55 /* first time */ 56 if (!drmdpy->config) { 57 struct native_config *nconf; 58 enum pipe_format format; 59 60 drmdpy->config = CALLOC(1, sizeof(*drmdpy->config)); 61 if (!drmdpy->config) 62 return NULL; 63 64 nconf = &drmdpy->config->base; 65 66 nconf->buffer_mask = 67 (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | 68 (1 << NATIVE_ATTACHMENT_BACK_LEFT); 69 70 format = PIPE_FORMAT_B8G8R8A8_UNORM; 71 if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) { 72 format = PIPE_FORMAT_A8R8G8B8_UNORM; 73 if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) 74 format = PIPE_FORMAT_NONE; 75 } 76 if (format == PIPE_FORMAT_NONE) { 77 FREE(drmdpy->config); 78 drmdpy->config = NULL; 79 return NULL; 80 } 81 82 nconf->color_format = format; 83 84 /* support KMS */ 85 if (drmdpy->resources) 86 nconf->scanout_bit = TRUE; 87 } 88 89 configs = MALLOC(sizeof(*configs)); 90 if (configs) { 91 configs[0] = &drmdpy->config->base; 92 if (num_configs) 93 *num_configs = 1; 94 } 95 96 return configs; 97} 98 99static int 100drm_display_get_param(struct native_display *ndpy, 101 enum native_param_type param) 102{ 103 int val; 104 105 switch (param) { 106 case NATIVE_PARAM_USE_NATIVE_BUFFER: 107 case NATIVE_PARAM_PRESERVE_BUFFER: 108 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 109 default: 110 val = 0; 111 break; 112 } 113 114 return val; 115} 116 117static void 118drm_display_destroy(struct native_display *ndpy) 119{ 120 struct drm_display *drmdpy = drm_display(ndpy); 121 122 if (drmdpy->config) 123 FREE(drmdpy->config); 124 125 drm_display_fini_modeset(&drmdpy->base); 126 127 if (drmdpy->base.screen) 128 drmdpy->base.screen->destroy(drmdpy->base.screen); 129 130 if (drmdpy->fd >= 0) 131 close(drmdpy->fd); 132 133 FREE(drmdpy); 134} 135 136static const char * 137get_drm_screen_name(int fd, drmVersionPtr version) 138{ 139 const char *name = version->name; 140 141 if (name && !strcmp(name, "radeon")) { 142 int chip_id; 143 struct drm_radeon_info info; 144 145 memset(&info, 0, sizeof(info)); 146 info.request = RADEON_INFO_DEVICE_ID; 147 info.value = pointer_to_intptr(&chip_id); 148 if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0) 149 return NULL; 150 151 name = is_r3xx(chip_id) ? "r300" : "r600"; 152 } 153 154 return name; 155} 156 157/** 158 * Initialize KMS and pipe screen. 159 */ 160static boolean 161drm_display_init_screen(struct native_display *ndpy) 162{ 163 struct drm_display *drmdpy = drm_display(ndpy); 164 drmVersionPtr version; 165 const char *name; 166 167 version = drmGetVersion(drmdpy->fd); 168 if (!version) { 169 _eglLog(_EGL_WARNING, "invalid fd %d", drmdpy->fd); 170 return FALSE; 171 } 172 173 name = get_drm_screen_name(drmdpy->fd, version); 174 if (name) { 175 drmdpy->base.screen = 176 drmdpy->event_handler->new_drm_screen(&drmdpy->base, name, drmdpy->fd); 177 } 178 drmFreeVersion(version); 179 180 if (!drmdpy->base.screen) { 181 _eglLog(_EGL_DEBUG, "failed to create DRM screen"); 182 return FALSE; 183 } 184 185 return TRUE; 186} 187 188static struct pipe_resource * 189drm_display_import_buffer(struct native_display *ndpy, 190 const struct pipe_resource *templ, 191 void *buf) 192{ 193 return ndpy->screen->resource_from_handle(ndpy->screen, 194 templ, (struct winsys_handle *) buf); 195} 196 197static boolean 198drm_display_export_buffer(struct native_display *ndpy, 199 struct pipe_resource *res, 200 void *buf) 201{ 202 return ndpy->screen->resource_get_handle(ndpy->screen, 203 res, (struct winsys_handle *) buf); 204} 205 206static struct native_display_buffer drm_display_buffer = { 207 drm_display_import_buffer, 208 drm_display_export_buffer 209}; 210 211static struct native_display * 212drm_create_display(int fd, struct native_event_handler *event_handler, 213 void *user_data) 214{ 215 struct drm_display *drmdpy; 216 217 drmdpy = CALLOC_STRUCT(drm_display); 218 if (!drmdpy) 219 return NULL; 220 221 drmdpy->fd = fd; 222 drmdpy->event_handler = event_handler; 223 drmdpy->base.user_data = user_data; 224 225 if (!drm_display_init_screen(&drmdpy->base)) { 226 drm_display_destroy(&drmdpy->base); 227 return NULL; 228 } 229 230 drmdpy->base.destroy = drm_display_destroy; 231 drmdpy->base.get_param = drm_display_get_param; 232 drmdpy->base.get_configs = drm_display_get_configs; 233 234 drmdpy->base.buffer = &drm_display_buffer; 235 drm_display_init_modeset(&drmdpy->base); 236 237 return &drmdpy->base; 238} 239 240static struct native_event_handler *drm_event_handler; 241 242static void 243native_set_event_handler(struct native_event_handler *event_handler) 244{ 245 drm_event_handler = event_handler; 246} 247 248static struct native_display * 249native_create_display(void *dpy, boolean use_sw, void *user_data) 250{ 251 int fd; 252 253 if (dpy) { 254 fd = dup((int) pointer_to_intptr(dpy)); 255 } 256 else { 257 fd = open("/dev/dri/card0", O_RDWR); 258 } 259 if (fd < 0) 260 return NULL; 261 262 return drm_create_display(fd, drm_event_handler, user_data); 263} 264 265static const struct native_platform drm_platform = { 266 "DRM", /* name */ 267 native_set_event_handler, 268 native_create_display 269}; 270 271const struct native_platform * 272native_get_drm_platform(void) 273{ 274 return &drm_platform; 275} 276