Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Mesa 3-D graphics library
3
 *
4
 * Copyright (C) 2010 Chia-I Wu 
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included
14
 * in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 */
24
 
25
#include 
26
#include 
27
#include 
28
#include 
29
#include 
30
 
31
#include "util/u_memory.h"
32
#include "egllog.h"
33
 
34
#include "native_drm.h"
35
 
36
#include "gbm_gallium_drmint.h"
37
 
38
#ifdef HAVE_LIBUDEV
39
#include 
40
#endif
41
 
42
static boolean
43
drm_display_is_format_supported(struct native_display *ndpy,
44
                                enum pipe_format fmt, boolean is_color)
45
{
46
   return ndpy->screen->is_format_supported(ndpy->screen,
47
         fmt, PIPE_TEXTURE_2D, 0,
48
         (is_color) ? PIPE_BIND_RENDER_TARGET :
49
         PIPE_BIND_DEPTH_STENCIL);
50
}
51
 
52
static const struct native_config **
53
drm_display_get_configs(struct native_display *ndpy, int *num_configs)
54
{
55
   struct drm_display *drmdpy = drm_display(ndpy);
56
   const struct native_config **configs;
57
 
58
   /* first time */
59
   if (!drmdpy->config) {
60
      struct native_config *nconf;
61
      enum pipe_format format;
62
 
63
      drmdpy->config = CALLOC(1, sizeof(*drmdpy->config));
64
      if (!drmdpy->config)
65
         return NULL;
66
 
67
      nconf = &drmdpy->config->base;
68
 
69
      nconf->buffer_mask =
70
         (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
71
         (1 << NATIVE_ATTACHMENT_BACK_LEFT);
72
 
73
      format = PIPE_FORMAT_B8G8R8A8_UNORM;
74
      if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) {
75
         format = PIPE_FORMAT_A8R8G8B8_UNORM;
76
         if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE))
77
            format = PIPE_FORMAT_NONE;
78
      }
79
      if (format == PIPE_FORMAT_NONE) {
80
         FREE(drmdpy->config);
81
         drmdpy->config = NULL;
82
         return NULL;
83
      }
84
 
85
      nconf->color_format = format;
86
 
87
      /* support KMS */
88
      if (drmdpy->resources)
89
         nconf->scanout_bit = TRUE;
90
   }
91
 
92
   configs = MALLOC(sizeof(*configs));
93
   if (configs) {
94
      configs[0] = &drmdpy->config->base;
95
      if (num_configs)
96
         *num_configs = 1;
97
   }
98
 
99
   return configs;
100
}
101
 
102
static int
103
drm_display_get_param(struct native_display *ndpy,
104
                      enum native_param_type param)
105
{
106
   int val;
107
 
108
   switch (param) {
109
   case NATIVE_PARAM_USE_NATIVE_BUFFER:
110
   case NATIVE_PARAM_PRESERVE_BUFFER:
111
   case NATIVE_PARAM_MAX_SWAP_INTERVAL:
112
   default:
113
      val = 0;
114
      break;
115
   }
116
 
117
   return val;
118
}
119
 
120
static void
121
drm_display_destroy(struct native_display *ndpy)
122
{
123
   struct drm_display *drmdpy = drm_display(ndpy);
124
 
125
   FREE(drmdpy->config);
126
 
127
   drm_display_fini_modeset(&drmdpy->base);
128
 
129
   /* gbm owns screen */
130
   ndpy->screen = NULL;
131
   ndpy_uninit(ndpy);
132
 
133
   FREE(drmdpy->device_name);
134
 
135
   if (drmdpy->own_gbm) {
136
      gbm_device_destroy(&drmdpy->gbmdrm->base.base);
137
      if (drmdpy->fd >= 0)
138
         close(drmdpy->fd);
139
   }
140
 
141
   FREE(drmdpy);
142
}
143
 
144
static struct native_display_buffer drm_display_buffer = {
145
   /* use the helpers */
146
   drm_display_import_native_buffer,
147
   drm_display_export_native_buffer
148
};
149
 
150
static char *
151
drm_get_device_name(int fd)
152
{
153
   char *device_name = NULL;
154
#ifdef HAVE_LIBUDEV
155
   struct udev *udev;
156
   struct udev_device *device;
157
   struct stat buf;
158
   const char *tmp;
159
 
160
   udev = udev_new();
161
   if (fstat(fd, &buf) < 0) {
162
      _eglLog(_EGL_WARNING, "failed to stat fd %d", fd);
163
      goto outudev;
164
   }
165
 
166
   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
167
   if (device == NULL) {
168
      _eglLog(_EGL_WARNING,
169
              "could not create udev device for fd %d", fd);
170
      goto outdevice;
171
   }
172
 
173
   tmp = udev_device_get_devnode(device);
174
   if (!tmp)
175
      goto outdevice;
176
   device_name = strdup(tmp);
177
 
178
outdevice:
179
   udev_device_unref(device);
180
outudev:
181
   udev_unref(udev);
182
 
183
#endif
184
   return device_name;
185
}
186
 
187
#ifdef HAVE_WAYLAND_BACKEND
188
 
189
static int
190
drm_display_authenticate(void *user_data, uint32_t magic)
191
{
192
   struct native_display *ndpy = user_data;
193
   struct drm_display *drmdpy = drm_display(ndpy);
194
 
195
   return drmAuthMagic(drmdpy->fd, magic);
196
}
197
 
198
static struct wayland_drm_callbacks wl_drm_callbacks = {
199
   drm_display_authenticate,
200
   egl_g3d_wl_drm_helper_reference_buffer,
201
   egl_g3d_wl_drm_helper_unreference_buffer
202
};
203
 
204
static boolean
205
drm_display_bind_wayland_display(struct native_display *ndpy,
206
                                  struct wl_display *wl_dpy)
207
{
208
   struct drm_display *drmdpy = drm_display(ndpy);
209
 
210
   if (drmdpy->wl_server_drm)
211
      return FALSE;
212
 
213
   drmdpy->wl_server_drm = wayland_drm_init(wl_dpy,
214
         drmdpy->device_name,
215
         &wl_drm_callbacks, ndpy, 0);
216
 
217
   if (!drmdpy->wl_server_drm)
218
      return FALSE;
219
 
220
   return TRUE;
221
}
222
 
223
static boolean
224
drm_display_unbind_wayland_display(struct native_display *ndpy,
225
                                    struct wl_display *wl_dpy)
226
{
227
   struct drm_display *drmdpy = drm_display(ndpy);
228
 
229
   if (!drmdpy->wl_server_drm)
230
      return FALSE;
231
 
232
   wayland_drm_uninit(drmdpy->wl_server_drm);
233
   drmdpy->wl_server_drm = NULL;
234
 
235
   return TRUE;
236
}
237
 
238
static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = {
239
   drm_display_bind_wayland_display,
240
   drm_display_unbind_wayland_display,
241
   egl_g3d_wl_drm_common_wl_buffer_get_resource,
242
   egl_g3d_wl_drm_common_query_buffer
243
};
244
 
245
#endif /* HAVE_WAYLAND_BACKEND */
246
 
247
static struct native_surface *
248
drm_create_pixmap_surface(struct native_display *ndpy,
249
                              EGLNativePixmapType pix,
250
                              const struct native_config *nconf)
251
{
252
   struct gbm_gallium_drm_bo *bo = (void *) pix;
253
 
254
   return drm_display_create_surface_from_resource(ndpy, bo->resource);
255
}
256
 
257
static boolean
258
drm_display_init_screen(struct native_display *ndpy)
259
{
260
   return TRUE;
261
}
262
 
263
static struct native_display *
264
drm_create_display(struct gbm_gallium_drm_device *gbmdrm, int own_gbm,
265
                   const struct native_event_handler *event_handler)
266
{
267
   struct drm_display *drmdpy;
268
 
269
   drmdpy = CALLOC_STRUCT(drm_display);
270
   if (!drmdpy)
271
      return NULL;
272
 
273
   drmdpy->gbmdrm = gbmdrm;
274
   drmdpy->own_gbm = own_gbm;
275
   drmdpy->fd = gbmdrm->base.base.fd;
276
   drmdpy->device_name = drm_get_device_name(drmdpy->fd);
277
 
278
   gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *))
279
      event_handler->lookup_egl_image;
280
   gbmdrm->lookup_egl_image_data = &drmdpy->base;
281
 
282
   drmdpy->event_handler = event_handler;
283
 
284
   drmdpy->base.screen = gbmdrm->screen;
285
 
286
   drmdpy->base.init_screen = drm_display_init_screen;
287
   drmdpy->base.destroy = drm_display_destroy;
288
   drmdpy->base.get_param = drm_display_get_param;
289
   drmdpy->base.get_configs = drm_display_get_configs;
290
 
291
   drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface;
292
 
293
   drmdpy->base.buffer = &drm_display_buffer;
294
#ifdef HAVE_WAYLAND_BACKEND
295
   if (drmdpy->device_name)
296
      drmdpy->base.wayland_bufmgr = &drm_display_wayland_bufmgr;
297
#endif
298
   drm_display_init_modeset(&drmdpy->base);
299
 
300
   return &drmdpy->base;
301
}
302
 
303
static const struct native_event_handler *drm_event_handler;
304
 
305
static struct native_display *
306
native_create_display(void *dpy, boolean use_sw)
307
{
308
   struct gbm_gallium_drm_device *gbm;
309
   int fd;
310
   int own_gbm = 0;
311
 
312
   gbm = dpy;
313
 
314
   if (gbm == NULL) {
315
      const char *device_name="/dev/dri/card0";
316
#ifdef O_CLOEXEC
317
      fd = open(device_name, O_RDWR | O_CLOEXEC);
318
      if (fd == -1 && errno == EINVAL)
319
#endif
320
      {
321
         fd = open(device_name, O_RDWR);
322
         if (fd != -1)
323
            fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
324
      }
325
      /* FIXME: Use an internal constructor to create a gbm
326
       * device with gallium backend directly, without setenv */
327
      setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
328
      gbm = gbm_gallium_drm_device(gbm_create_device(fd));
329
      own_gbm = 1;
330
   }
331
 
332
   if (gbm == NULL)
333
      return NULL;
334
 
335
   if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 ||
336
       gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) {
337
      if (own_gbm)
338
         gbm_device_destroy(&gbm->base.base);
339
      return NULL;
340
   }
341
 
342
   return drm_create_display(gbm, own_gbm, drm_event_handler);
343
}
344
 
345
static const struct native_platform drm_platform = {
346
   "DRM", /* name */
347
   native_create_display
348
};
349
 
350
const struct native_platform *
351
native_get_drm_platform(const struct native_event_handler *event_handler)
352
{
353
   drm_event_handler = event_handler;
354
   return &drm_platform;
355
}