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) 2011 Benjamin Franzke 
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 "util/u_memory.h"
26
#include "util/u_inlines.h"
27
 
28
#include "pipe/p_compiler.h"
29
#include "pipe/p_screen.h"
30
#include "pipe/p_context.h"
31
#include "pipe/p_state.h"
32
#include "state_tracker/drm_driver.h"
33
 
34
#include "egllog.h"
35
#include 
36
 
37
#include "native_wayland.h"
38
 
39
#include 
40
#include "wayland-drm-client-protocol.h"
41
#include "wayland-egl-priv.h"
42
 
43
#include "common/native_wayland_drm_bufmgr_helper.h"
44
 
45
#include 
46
#include 
47
#include 
48
#include 
49
 
50
struct wayland_drm_display {
51
   struct wayland_display base;
52
 
53
   const struct native_event_handler *event_handler;
54
 
55
   struct wl_drm *wl_drm;
56
   struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
57
   int fd;
58
   char *device_name;
59
   boolean authenticated;
60
};
61
 
62
static INLINE struct wayland_drm_display *
63
wayland_drm_display(const struct native_display *ndpy)
64
{
65
   return (struct wayland_drm_display *) ndpy;
66
}
67
 
68
static void
69
wayland_drm_display_destroy(struct native_display *ndpy)
70
{
71
   struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
72
 
73
   if (drmdpy->wl_drm)
74
      wl_drm_destroy(drmdpy->wl_drm);
75
   FREE(drmdpy->device_name);
76
   FREE(drmdpy->base.configs);
77
   if (drmdpy->base.own_dpy)
78
      wl_display_disconnect(drmdpy->base.dpy);
79
 
80
   ndpy_uninit(ndpy);
81
 
82
   if (drmdpy->fd)
83
      close(drmdpy->fd);
84
 
85
   FREE(drmdpy);
86
}
87
 
88
static struct wl_buffer *
89
wayland_create_drm_buffer(struct wayland_display *display,
90
                          struct wayland_surface *surface,
91
                          enum native_attachment attachment)
92
{
93
   struct wayland_drm_display *drmdpy = (struct wayland_drm_display *) display;
94
   struct pipe_screen *screen = drmdpy->base.base.screen;
95
   struct pipe_resource *resource;
96
   struct winsys_handle wsh;
97
   uint width, height;
98
   enum wl_drm_format format;
99
 
100
   resource = resource_surface_get_single_resource(surface->rsurf, attachment);
101
   resource_surface_get_size(surface->rsurf, &width, &height);
102
 
103
   wsh.type = DRM_API_HANDLE_TYPE_SHARED;
104
   screen->resource_get_handle(screen, resource, &wsh);
105
 
106
   pipe_resource_reference(&resource, NULL);
107
 
108
   switch (surface->color_format) {
109
   case PIPE_FORMAT_B8G8R8A8_UNORM:
110
      format = WL_DRM_FORMAT_ARGB8888;
111
      break;
112
   case PIPE_FORMAT_B8G8R8X8_UNORM:
113
      format = WL_DRM_FORMAT_XRGB8888;
114
      break;
115
   default:
116
      return NULL;
117
      break;
118
   }
119
 
120
   return wl_drm_create_buffer(drmdpy->wl_drm, wsh.handle,
121
                               width, height, wsh.stride, format);
122
}
123
 
124
static void
125
drm_handle_device(void *data, struct wl_drm *drm, const char *device)
126
{
127
   struct wayland_drm_display *drmdpy = data;
128
   drm_magic_t magic;
129
 
130
   drmdpy->device_name = strdup(device);
131
   if (!drmdpy->device_name)
132
      return;
133
 
134
#ifdef O_CLOEXEC
135
   drmdpy->fd = open(drmdpy->device_name, O_RDWR | O_CLOEXEC);
136
   if (drmdpy->fd == -1 && errno == EINVAL)
137
#endif
138
   {
139
      drmdpy->fd = open(drmdpy->device_name, O_RDWR);
140
      if (drmdpy->fd != -1)
141
         fcntl(drmdpy->fd, F_SETFD, fcntl(drmdpy->fd, F_GETFD) | FD_CLOEXEC);
142
   }
143
   if (drmdpy->fd == -1) {
144
      _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)",
145
              drmdpy->device_name, strerror(errno));
146
      return;
147
   }
148
 
149
   drmGetMagic(drmdpy->fd, &magic);
150
   wl_drm_authenticate(drmdpy->wl_drm, magic);
151
}
152
 
153
static void
154
drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
155
{
156
   struct wayland_drm_display *drmdpy = data;
157
 
158
   switch (format) {
159
   case WL_DRM_FORMAT_ARGB8888:
160
      drmdpy->base.formats |= HAS_ARGB8888;
161
      break;
162
   case WL_DRM_FORMAT_XRGB8888:
163
      drmdpy->base.formats |= HAS_XRGB8888;
164
      break;
165
   }
166
}
167
 
168
static void
169
drm_handle_authenticated(void *data, struct wl_drm *drm)
170
{
171
   struct wayland_drm_display *drmdpy = data;
172
 
173
   drmdpy->authenticated = true;
174
}
175
 
176
static const struct wl_drm_listener drm_listener = {
177
   drm_handle_device,
178
   drm_handle_format,
179
   drm_handle_authenticated
180
};
181
 
182
static void
183
registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
184
                       const char *interface, uint32_t version)
185
{
186
   struct wayland_drm_display *drmdpy = data;
187
 
188
   if (strcmp(interface, "wl_drm") == 0) {
189
      drmdpy->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, 1);
190
      wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
191
   }
192
}
193
 
194
static const struct wl_registry_listener registry_listener = {
195
       registry_handle_global
196
};
197
 
198
static boolean
199
wayland_drm_display_init_screen(struct native_display *ndpy)
200
{
201
   struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
202
 
203
   drmdpy->base.queue = wl_display_create_queue(drmdpy->base.dpy);
204
   drmdpy->base.registry = wl_display_get_registry(drmdpy->base.dpy);
205
   wl_proxy_set_queue((struct wl_proxy *) drmdpy->base.registry,
206
                      drmdpy->base.queue);
207
   wl_registry_add_listener(drmdpy->base.registry, ®istry_listener, drmdpy);
208
   if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->wl_drm == NULL)
209
      return FALSE;
210
 
211
   wl_drm_add_listener(drmdpy->wl_drm, &drm_listener, drmdpy);
212
   if (wayland_roundtrip(&drmdpy->base) < 0 || drmdpy->fd == -1)
213
      return FALSE;
214
 
215
   if (wayland_roundtrip(&drmdpy->base) < 0 || !drmdpy->authenticated)
216
      return FALSE;
217
 
218
   if (drmdpy->base.formats == 0)
219
      return FALSE;
220
 
221
   drmdpy->base.base.screen =
222
      drmdpy->event_handler->new_drm_screen(&drmdpy->base.base,
223
                                            NULL, drmdpy->fd);
224
   if (!drmdpy->base.base.screen) {
225
      _eglLog(_EGL_WARNING, "failed to create DRM screen");
226
      return FALSE;
227
   }
228
 
229
   return TRUE;
230
}
231
 
232
static struct native_display_buffer wayland_drm_display_buffer = {
233
   /* use the helpers */
234
   drm_display_import_native_buffer,
235
   drm_display_export_native_buffer
236
};
237
 
238
static int
239
wayland_drm_display_authenticate(void *user_data, uint32_t magic)
240
{
241
   struct native_display *ndpy = user_data;
242
   struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
243
   boolean current_authenticate, authenticated;
244
 
245
   current_authenticate = drmdpy->authenticated;
246
 
247
   wl_drm_authenticate(drmdpy->wl_drm, magic);
248
   wl_display_roundtrip(drmdpy->base.dpy);
249
   authenticated = drmdpy->authenticated;
250
 
251
   drmdpy->authenticated = current_authenticate;
252
 
253
   return authenticated ? 0 : -1;
254
}
255
 
256
static struct wayland_drm_callbacks wl_drm_callbacks = {
257
   wayland_drm_display_authenticate,
258
   egl_g3d_wl_drm_helper_reference_buffer,
259
   egl_g3d_wl_drm_helper_unreference_buffer
260
};
261
 
262
static boolean
263
wayland_drm_display_bind_wayland_display(struct native_display *ndpy,
264
                                         struct wl_display *wl_dpy)
265
{
266
   struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
267
 
268
   if (drmdpy->wl_server_drm)
269
      return FALSE;
270
 
4401 Serge 271
   ndpy->wl_server_drm =
4358 Serge 272
      wayland_drm_init(wl_dpy, drmdpy->device_name,
273
                       &wl_drm_callbacks, ndpy, 0);
274
 
275
   if (!drmdpy->wl_server_drm)
276
      return FALSE;
277
 
278
   return TRUE;
279
}
280
 
281
static boolean
282
wayland_drm_display_unbind_wayland_display(struct native_display *ndpy,
283
                                           struct wl_display *wl_dpy)
284
{
285
   struct wayland_drm_display *drmdpy = wayland_drm_display(ndpy);
286
 
287
   if (!drmdpy->wl_server_drm)
288
      return FALSE;
289
 
290
   wayland_drm_uninit(drmdpy->wl_server_drm);
291
   drmdpy->wl_server_drm = NULL;
292
 
293
   return TRUE;
294
}
295
 
296
static struct native_display_wayland_bufmgr wayland_drm_display_wayland_bufmgr = {
297
   wayland_drm_display_bind_wayland_display,
298
   wayland_drm_display_unbind_wayland_display,
299
   egl_g3d_wl_drm_common_wl_buffer_get_resource,
300
   egl_g3d_wl_drm_common_query_buffer
301
};
302
 
303
 
304
struct wayland_display *
305
wayland_create_drm_display(struct wl_display *dpy,
306
                           const struct native_event_handler *event_handler)
307
{
308
   struct wayland_drm_display *drmdpy;
309
 
310
   drmdpy = CALLOC_STRUCT(wayland_drm_display);
311
   if (!drmdpy)
312
      return NULL;
313
 
314
   drmdpy->event_handler = event_handler;
315
 
316
   drmdpy->base.dpy = dpy;
317
   if (!drmdpy->base.dpy) {
318
      wayland_drm_display_destroy(&drmdpy->base.base);
319
      return NULL;
320
   }
321
 
322
   drmdpy->base.base.init_screen = wayland_drm_display_init_screen;
323
   drmdpy->base.base.destroy = wayland_drm_display_destroy;
324
   drmdpy->base.base.buffer = &wayland_drm_display_buffer;
325
   drmdpy->base.base.wayland_bufmgr = &wayland_drm_display_wayland_bufmgr;
326
 
327
   drmdpy->base.create_buffer = wayland_create_drm_buffer;
328
 
329
   return &drmdpy->base;
330
}
331
 
332
/* vim: set sw=3 ts=8 sts=3 expandtab: */