tizen 2.4 release
[sdk/emulator-yagl.git] / EGL / x11 / yagl_x11_display.c
1 /*
2  * YaGL
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact :
7  * Stanislav Vorobiov <s.vorobiov@samsung.com>
8  * Jinhyung Jo <jinhyung.jo@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27  * THE SOFTWARE.
28  *
29  * Contributors:
30  * - S-Core Co., Ltd
31  *
32  */
33
34 #include "yagl_x11_display.h"
35 #include "yagl_x11_drawable.h"
36 #include "yagl_x11_image.h"
37 #include "yagl_native_platform.h"
38 #include "yagl_log.h"
39 #include "yagl_malloc.h"
40 #include "yagl_dri2.h"
41 #include "yagl_dri3.h"
42 #include "vigs.h"
43 #include <X11/Xutil.h>
44 #include <X11/extensions/XShm.h>
45 #include <sys/fcntl.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48
49 static int yagl_x11_display_dri2_authenticate(Display *x_dpy, uint32_t id)
50 {
51     if (!yagl_DRI2Authenticate(x_dpy,
52                                RootWindow(x_dpy, DefaultScreen(x_dpy)),
53                                id)) {
54         fprintf(stderr, "Critical error! Failed to DRI2Authenticate on YaGL display, DRI2 not enabled ?\n");
55         return 0;
56     }
57
58     return 1;
59 }
60
61 static int yagl_x11_display_dri2_init(Display *x_dpy, char **dri_device)
62 {
63     int ret;
64     int event_base, error_base;
65     int dri_major, dri_minor;
66     char *dri_driver = NULL;
67     int drm_fd = -1;
68     drm_magic_t magic;
69
70     YAGL_LOG_FUNC_SET(eglGetDisplay);
71
72     *dri_device = NULL;
73
74     if (!yagl_DRI2QueryExtension(x_dpy, &event_base, &error_base)) {
75         fprintf(stderr, "Critical error! Failed to DRI2QueryExtension on YaGL display, DRI2 not enabled ?\n");
76         goto fail;
77     }
78
79     YAGL_LOG_TRACE("DRI2QueryExtension returned %d %d",
80                    event_base, error_base);
81
82     if (!yagl_DRI2QueryVersion(x_dpy, &dri_major, &dri_minor)) {
83         fprintf(stderr, "Critical error! Failed to DRI2QueryVersion on YaGL display, DRI2 not enabled ?\n");
84         goto fail;
85     }
86
87     YAGL_LOG_TRACE("DRI2QueryVersion returned %d %d",
88                    dri_major, dri_minor);
89
90     if (!yagl_DRI2Connect(x_dpy,
91                           RootWindow(x_dpy, DefaultScreen(x_dpy)),
92                           &dri_driver,
93                           dri_device)) {
94         fprintf(stderr, "Critical error! Failed to DRI2Connect on YaGL display, DRI2 not enabled ?\n");
95         goto fail;
96     }
97
98     YAGL_LOG_TRACE("DRI2Connect returned %s %s",
99                    dri_driver, *dri_device);
100
101     drm_fd = open(*dri_device, O_RDWR);
102
103     if (drm_fd < 0) {
104         fprintf(stderr, "Critical error! Failed to open(\"%s\"): %s\n", *dri_device, strerror(errno));
105         goto fail;
106     }
107
108     memset(&magic, 0, sizeof(magic));
109
110     ret = drmGetMagic(drm_fd, &magic);
111
112     if (ret != 0) {
113         fprintf(stderr, "Critical error! drmGetMagic failed: %s\n", strerror(-ret));
114         goto fail;
115     }
116
117     if (!yagl_x11_display_dri2_authenticate(x_dpy, magic)) {
118         goto fail;
119     }
120
121     goto out;
122
123 fail:
124     if (drm_fd >= 0) {
125         close(drm_fd);
126         drm_fd = -1;
127     }
128     if (*dri_device) {
129         Xfree(*dri_device);
130     }
131 out:
132     if (dri_driver) {
133         Xfree(dri_driver);
134     }
135
136     return drm_fd;
137 }
138
139 static int yagl_x11_display_authenticate(struct yagl_native_display *dpy,
140                                          uint32_t id)
141 {
142     struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy;
143     Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy);
144
145     if (!x11_dpy->dri3_supported) {
146         return yagl_x11_display_dri2_authenticate(x_dpy, id);
147     }
148
149     return 1;
150 }
151
152 static struct yagl_native_drawable
153     *yagl_x11_display_wrap_window(struct yagl_native_display *dpy,
154                                   yagl_os_window os_window)
155 {
156     struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy;
157
158     return x11_dpy->create_drawable(dpy, os_window, 0, 0);
159 }
160
161 static struct yagl_native_drawable
162     *yagl_x11_display_wrap_pixmap(struct yagl_native_display *dpy,
163                                   yagl_os_pixmap os_pixmap)
164 {
165     struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy;
166
167     return x11_dpy->create_drawable(dpy, os_pixmap, 0, 1);
168 }
169
170 static struct yagl_native_drawable
171     *yagl_x11_display_create_pixmap(struct yagl_native_display *dpy,
172                                     uint32_t width,
173                                     uint32_t height,
174                                     uint32_t depth)
175 {
176     struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy;
177     struct yagl_native_drawable *drawable;
178     Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy);
179     Pixmap x_pixmap = XCreatePixmap(x_dpy,
180                                     RootWindow(x_dpy, DefaultScreen(x_dpy)),
181                                     width, height, depth);
182
183     if (!x_pixmap) {
184         return NULL;
185     }
186
187     drawable = x11_dpy->create_drawable(dpy, (yagl_os_pixmap)x_pixmap, 1, 1);
188
189     if (!drawable) {
190         XFreePixmap(x_dpy, x_pixmap);
191         return NULL;
192     }
193
194     return drawable;
195 }
196
197 static struct yagl_native_image
198     *yagl_x11_display_create_image(struct yagl_native_display *dpy,
199                                    uint32_t width,
200                                    uint32_t height,
201                                    uint32_t depth)
202 {
203     return yagl_x11_image_create(dpy, width, height, depth);
204 }
205
206 static int yagl_x11_display_get_visual(struct yagl_native_display *dpy,
207                                        int *visual_id,
208                                        int *visual_type)
209 {
210     Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy);
211     int screen;
212     XVisualInfo vi;
213
214     screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(x_dpy));
215
216     /*
217      * 24-bit is the highest supported by soft framebuffer.
218      */
219     if (!XMatchVisualInfo(x_dpy, screen, 24, TrueColor, &vi)) {
220         return 0;
221     }
222
223     *visual_id = XVisualIDFromVisual(vi.visual);
224     *visual_type = TrueColor;
225
226     return 1;
227 }
228
229 static void yagl_x11_display_destroy(struct yagl_native_display *dpy)
230 {
231     struct yagl_x11_display *x11_dpy = (struct yagl_x11_display*)dpy;
232     Display *x_dpy = YAGL_X11_DPY(dpy->os_dpy);
233
234     if (dpy->drm_dev) {
235         int fd = dpy->drm_dev->fd;
236         vigs_drm_device_destroy(dpy->drm_dev);
237         close(fd);
238     }
239
240     yagl_native_display_cleanup(dpy);
241
242     if (x11_dpy->own_dpy) {
243         XCloseDisplay(x_dpy);
244     }
245
246     yagl_free(x11_dpy);
247 }
248
249 struct yagl_native_display *yagl_x11_display_create(struct yagl_native_platform *platform,
250                                                     yagl_os_display os_dpy,
251                                                     int own_dpy,
252                                                     int enable_drm)
253 {
254     Display *x_dpy = YAGL_X11_DPY(os_dpy);
255     struct yagl_x11_display *dpy;
256     int xmajor;
257     int xminor;
258     Bool pixmaps;
259     struct vigs_drm_device *drm_dev = NULL;
260     char *dri_device = NULL;
261     int ret;
262
263     YAGL_LOG_FUNC_SET(eglGetDisplay);
264
265     dpy = yagl_malloc0(sizeof(*dpy));
266
267     dpy->own_dpy = own_dpy;
268
269     dpy->xshm_images_supported = XShmQueryVersion(x_dpy,
270                                                   &xmajor,
271                                                   &xminor,
272                                                   &pixmaps);
273     dpy->xshm_pixmaps_supported = pixmaps;
274
275     YAGL_LOG_DEBUG("XShm images are%s supported, version %d, %d (pixmaps = %d)",
276                    (dpy->xshm_images_supported ? "" : " NOT"),
277                    xmajor,
278                    xminor,
279                    pixmaps);
280
281     dpy->create_drawable = &yagl_x11_drawable_create;
282
283     if (enable_drm) {
284         int drm_fd = yagl_dri3_display_init(x_dpy, &dri_device);
285
286         if (drm_fd < 0) {
287             YAGL_LOG_DEBUG("DRI3 init failed. Falling back to DRI2...");
288
289             drm_fd = yagl_x11_display_dri2_init(x_dpy, &dri_device);
290
291             if (drm_fd < 0) {
292                 yagl_free(dpy);
293                 return NULL;
294             }
295         } else {
296             dpy->create_drawable = &yagl_dri3_drawable_create;
297             dpy->dri3_supported = 1;
298             platform->buffer_age_supported = 1;
299         }
300
301         ret = vigs_drm_device_create(drm_fd, &drm_dev);
302
303         if (ret != 0) {
304             fprintf(stderr,
305                     "Critical error! vigs_drm_device_create failed: %s\n",
306                     strerror(-ret));
307             close(drm_fd);
308             Xfree(dri_device);
309             yagl_free(dpy);
310             return NULL;
311         }
312     }
313
314     yagl_native_display_init(&dpy->base,
315                              platform,
316                              os_dpy,
317                              drm_dev,
318                              dri_device);
319
320     dpy->base.authenticate = &yagl_x11_display_authenticate;
321     dpy->base.wrap_window = &yagl_x11_display_wrap_window;
322     dpy->base.wrap_pixmap = &yagl_x11_display_wrap_pixmap;
323     dpy->base.create_pixmap = &yagl_x11_display_create_pixmap;
324     dpy->base.create_image = &yagl_x11_display_create_image;
325     dpy->base.get_visual = &yagl_x11_display_get_visual;
326     dpy->base.destroy = &yagl_x11_display_destroy;
327
328     if (dri_device) {
329         Xfree(dri_device);
330     }
331
332     return &dpy->base;
333 }