Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | 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
 
4401 Serge 42
#ifdef HAVE_WAYLAND_BACKEND
43
#include "common/native_wayland_drm_bufmgr_helper.h"
44
#endif
45
 
4358 Serge 46
static boolean
47
drm_display_is_format_supported(struct native_display *ndpy,
48
                                enum pipe_format fmt, boolean is_color)
49
{
50
   return ndpy->screen->is_format_supported(ndpy->screen,
51
         fmt, PIPE_TEXTURE_2D, 0,
52
         (is_color) ? PIPE_BIND_RENDER_TARGET :
53
         PIPE_BIND_DEPTH_STENCIL);
54
}
55
 
56
static const struct native_config **
57
drm_display_get_configs(struct native_display *ndpy, int *num_configs)
58
{
59
   struct drm_display *drmdpy = drm_display(ndpy);
60
   const struct native_config **configs;
61
 
62
   /* first time */
63
   if (!drmdpy->config) {
64
      struct native_config *nconf;
65
      enum pipe_format format;
66
 
67
      drmdpy->config = CALLOC(1, sizeof(*drmdpy->config));
68
      if (!drmdpy->config)
69
         return NULL;
70
 
71
      nconf = &drmdpy->config->base;
72
 
73
      nconf->buffer_mask =
74
         (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
75
         (1 << NATIVE_ATTACHMENT_BACK_LEFT);
76
 
77
      format = PIPE_FORMAT_B8G8R8A8_UNORM;
78
      if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE)) {
79
         format = PIPE_FORMAT_A8R8G8B8_UNORM;
80
         if (!drm_display_is_format_supported(&drmdpy->base, format, TRUE))
81
            format = PIPE_FORMAT_NONE;
82
      }
83
      if (format == PIPE_FORMAT_NONE) {
84
         FREE(drmdpy->config);
85
         drmdpy->config = NULL;
86
         return NULL;
87
      }
88
 
89
      nconf->color_format = format;
90
 
91
      /* support KMS */
92
      if (drmdpy->resources)
93
         nconf->scanout_bit = TRUE;
94
   }
95
 
96
   configs = MALLOC(sizeof(*configs));
97
   if (configs) {
98
      configs[0] = &drmdpy->config->base;
99
      if (num_configs)
100
         *num_configs = 1;
101
   }
102
 
103
   return configs;
104
}
105
 
106
static int
107
drm_display_get_param(struct native_display *ndpy,
108
                      enum native_param_type param)
109
{
110
   int val;
111
 
112
   switch (param) {
113
   case NATIVE_PARAM_USE_NATIVE_BUFFER:
114
   case NATIVE_PARAM_PRESERVE_BUFFER:
115
   case NATIVE_PARAM_MAX_SWAP_INTERVAL:
116
   default:
117
      val = 0;
118
      break;
119
   }
120
 
121
   return val;
122
}
123
 
124
static void
125
drm_display_destroy(struct native_display *ndpy)
126
{
127
   struct drm_display *drmdpy = drm_display(ndpy);
128
 
129
   FREE(drmdpy->config);
130
 
131
   drm_display_fini_modeset(&drmdpy->base);
132
 
133
   /* gbm owns screen */
134
   ndpy->screen = NULL;
135
   ndpy_uninit(ndpy);
136
 
137
   FREE(drmdpy->device_name);
138
 
139
   if (drmdpy->own_gbm) {
140
      gbm_device_destroy(&drmdpy->gbmdrm->base.base);
141
      if (drmdpy->fd >= 0)
142
         close(drmdpy->fd);
143
   }
144
 
145
   FREE(drmdpy);
146
}
147
 
148
static struct native_display_buffer drm_display_buffer = {
149
   /* use the helpers */
150
   drm_display_import_native_buffer,
151
   drm_display_export_native_buffer
152
};
153
 
154
static char *
155
drm_get_device_name(int fd)
156
{
157
   char *device_name = NULL;
158
#ifdef HAVE_LIBUDEV
159
   struct udev *udev;
160
   struct udev_device *device;
161
   struct stat buf;
162
   const char *tmp;
163
 
164
   udev = udev_new();
165
   if (fstat(fd, &buf) < 0) {
166
      _eglLog(_EGL_WARNING, "failed to stat fd %d", fd);
167
      goto outudev;
168
   }
169
 
170
   device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
171
   if (device == NULL) {
172
      _eglLog(_EGL_WARNING,
173
              "could not create udev device for fd %d", fd);
174
      goto outdevice;
175
   }
176
 
177
   tmp = udev_device_get_devnode(device);
178
   if (!tmp)
179
      goto outdevice;
180
   device_name = strdup(tmp);
181
 
182
outdevice:
183
   udev_device_unref(device);
184
outudev:
185
   udev_unref(udev);
186
 
187
#endif
188
   return device_name;
189
}
190
 
191
#ifdef HAVE_WAYLAND_BACKEND
192
 
193
static int
194
drm_display_authenticate(void *user_data, uint32_t magic)
195
{
196
   struct native_display *ndpy = user_data;
197
   struct drm_display *drmdpy = drm_display(ndpy);
198
 
199
   return drmAuthMagic(drmdpy->fd, magic);
200
}
201
 
202
static struct wayland_drm_callbacks wl_drm_callbacks = {
203
   drm_display_authenticate,
204
   egl_g3d_wl_drm_helper_reference_buffer,
205
   egl_g3d_wl_drm_helper_unreference_buffer
206
};
207
 
208
static boolean
209
drm_display_bind_wayland_display(struct native_display *ndpy,
210
                                  struct wl_display *wl_dpy)
211
{
212
   struct drm_display *drmdpy = drm_display(ndpy);
213
 
4401 Serge 214
   if (ndpy->wl_server_drm)
4358 Serge 215
      return FALSE;
216
 
4401 Serge 217
   ndpy->wl_server_drm = wayland_drm_init(wl_dpy,
4358 Serge 218
         drmdpy->device_name,
219
         &wl_drm_callbacks, ndpy, 0);
220
 
4401 Serge 221
   if (!ndpy->wl_server_drm)
4358 Serge 222
      return FALSE;
223
 
224
   return TRUE;
225
}
226
 
227
static boolean
228
drm_display_unbind_wayland_display(struct native_display *ndpy,
229
                                    struct wl_display *wl_dpy)
230
{
4401 Serge 231
   if (!ndpy->wl_server_drm)
4358 Serge 232
      return FALSE;
233
 
4401 Serge 234
   wayland_drm_uninit(ndpy->wl_server_drm);
235
   ndpy->wl_server_drm = NULL;
4358 Serge 236
 
237
   return TRUE;
238
}
239
 
240
static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = {
241
   drm_display_bind_wayland_display,
242
   drm_display_unbind_wayland_display,
243
   egl_g3d_wl_drm_common_wl_buffer_get_resource,
244
   egl_g3d_wl_drm_common_query_buffer
245
};
246
 
247
#endif /* HAVE_WAYLAND_BACKEND */
248
 
249
static struct native_surface *
250
drm_create_pixmap_surface(struct native_display *ndpy,
251
                              EGLNativePixmapType pix,
252
                              const struct native_config *nconf)
253
{
254
   struct gbm_gallium_drm_bo *bo = (void *) pix;
255
 
256
   return drm_display_create_surface_from_resource(ndpy, bo->resource);
257
}
258
 
259
static boolean
260
drm_display_init_screen(struct native_display *ndpy)
261
{
262
   return TRUE;
263
}
264
 
265
static struct native_display *
266
drm_create_display(struct gbm_gallium_drm_device *gbmdrm, int own_gbm,
267
                   const struct native_event_handler *event_handler)
268
{
269
   struct drm_display *drmdpy;
270
 
271
   drmdpy = CALLOC_STRUCT(drm_display);
272
   if (!drmdpy)
273
      return NULL;
274
 
275
   drmdpy->gbmdrm = gbmdrm;
276
   drmdpy->own_gbm = own_gbm;
277
   drmdpy->fd = gbmdrm->base.base.fd;
278
   drmdpy->device_name = drm_get_device_name(drmdpy->fd);
279
 
280
   gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *))
281
      event_handler->lookup_egl_image;
282
   gbmdrm->lookup_egl_image_data = &drmdpy->base;
283
 
284
   drmdpy->event_handler = event_handler;
285
 
286
   drmdpy->base.screen = gbmdrm->screen;
287
 
288
   drmdpy->base.init_screen = drm_display_init_screen;
289
   drmdpy->base.destroy = drm_display_destroy;
290
   drmdpy->base.get_param = drm_display_get_param;
291
   drmdpy->base.get_configs = drm_display_get_configs;
292
 
293
   drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface;
294
 
295
   drmdpy->base.buffer = &drm_display_buffer;
296
#ifdef HAVE_WAYLAND_BACKEND
297
   if (drmdpy->device_name)
298
      drmdpy->base.wayland_bufmgr = &drm_display_wayland_bufmgr;
299
#endif
300
   drm_display_init_modeset(&drmdpy->base);
301
 
302
   return &drmdpy->base;
303
}
304
 
305
static const struct native_event_handler *drm_event_handler;
306
 
307
static struct native_display *
308
native_create_display(void *dpy, boolean use_sw)
309
{
310
   struct gbm_gallium_drm_device *gbm;
311
   int fd;
312
   int own_gbm = 0;
313
 
314
   gbm = dpy;
315
 
316
   if (gbm == NULL) {
317
      const char *device_name="/dev/dri/card0";
318
#ifdef O_CLOEXEC
319
      fd = open(device_name, O_RDWR | O_CLOEXEC);
320
      if (fd == -1 && errno == EINVAL)
321
#endif
322
      {
323
         fd = open(device_name, O_RDWR);
324
         if (fd != -1)
325
            fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
326
      }
327
      /* FIXME: Use an internal constructor to create a gbm
328
       * device with gallium backend directly, without setenv */
329
      setenv("GBM_BACKEND", "gbm_gallium_drm.so", 1);
330
      gbm = gbm_gallium_drm_device(gbm_create_device(fd));
331
      own_gbm = 1;
332
   }
333
 
334
   if (gbm == NULL)
335
      return NULL;
336
 
337
   if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 ||
338
       gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) {
339
      if (own_gbm)
340
         gbm_device_destroy(&gbm->base.base);
341
      return NULL;
342
   }
343
 
344
   return drm_create_display(gbm, own_gbm, drm_event_handler);
345
}
346
 
347
static const struct native_platform drm_platform = {
348
   "DRM", /* name */
349
   native_create_display
350
};
351
 
352
const struct native_platform *
353
native_get_drm_platform(const struct native_event_handler *event_handler)
354
{
355
   drm_event_handler = event_handler;
356
   return &drm_platform;
357
}