521c91d8958484d2bbcefcfbf38d620d421d7bd4
[mesa.git] / src / gallium / state_trackers / egl / egl_tracker.c
1
2 #include "utils.h"
3
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include "egl_tracker.h"
8
9 #include "egllog.h"
10 #include "state_tracker/drm_api.h"
11
12 #include "pipe/p_screen.h"
13 #include "pipe/internal/p_winsys_screen.h"
14
15 /** HACK */
16 void* driDriverAPI;
17 extern const struct dri_extension card_extensions[];
18
19
20 /*
21 * Exported functions
22 */
23
24 /**
25 * The bootstrap function. Return a new drm_driver object and
26 * plug in API functions.
27 */
28 _EGLDriver *
29 _eglMain(_EGLDisplay *dpy, const char *args)
30 {
31 struct drm_device *drm;
32
33 drm = (struct drm_device *) calloc(1, sizeof(struct drm_device));
34 if (!drm) {
35 return NULL;
36 }
37
38 drm->api = drm_api_create();
39
40 /* First fill in the dispatch table with defaults */
41 _eglInitDriverFallbacks(&drm->base);
42 /* then plug in our Drm-specific functions */
43 drm->base.API.Initialize = drm_initialize;
44 drm->base.API.Terminate = drm_terminate;
45 drm->base.API.CreateContext = drm_create_context;
46 drm->base.API.MakeCurrent = drm_make_current;
47 drm->base.API.CreateWindowSurface = drm_create_window_surface;
48 drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface;
49 drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface;
50 drm->base.API.DestroySurface = drm_destroy_surface;
51 drm->base.API.DestroyContext = drm_destroy_context;
52 drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa;
53 drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa;
54 drm->base.API.SwapBuffers = drm_swap_buffers;
55
56 drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/;
57 drm->base.Name = "DRM/Gallium/Win";
58
59 /* enable supported extensions */
60 drm->base.Extensions.MESA_screen_surface = EGL_TRUE;
61 drm->base.Extensions.MESA_copy_context = EGL_TRUE;
62
63 return &drm->base;
64 }
65
66 static void
67 drm_get_device_id(struct drm_device *device)
68 {
69 char path[512];
70 FILE *file;
71 char *ret;
72
73 /* TODO get the real minor */
74 int minor = 0;
75
76 device->deviceID = 0;
77
78 snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor);
79 file = fopen(path, "r");
80 if (!file) {
81 _eglLog(_EGL_WARNING, "Could not retrive device ID\n");
82 return;
83 }
84
85 ret = fgets(path, sizeof( path ), file);
86 if (!ret)
87 return;
88
89 sscanf(path, "%x", &device->deviceID);
90 fclose(file);
91 }
92
93 static void
94 drm_update_res(struct drm_device *dev)
95 {
96 drmModeFreeResources(dev->res);
97 dev->res = drmModeGetResources(dev->drmFD);
98 }
99
100 static void
101 drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector)
102 {
103 drmModeModeInfoPtr m = NULL;
104 int i;
105
106 for (i = 0; i < connector->count_modes; i++) {
107 m = &connector->modes[i];
108 _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name);
109 }
110 }
111
112 static void
113 drm_find_dpms(struct drm_device *dev, struct drm_screen *screen)
114 {
115 drmModeConnectorPtr c = screen->connector;
116 drmModePropertyPtr p;
117 int i;
118
119 for (i = 0; i < c->count_props; i++) {
120 p = drmModeGetProperty(dev->drmFD, c->props[i]);
121 if (!strcmp(p->name, "DPMS"))
122 break;
123
124 drmModeFreeProperty(p);
125 p = NULL;
126 }
127
128 screen->dpms = p;
129 }
130
131 EGLBoolean
132 drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
133 {
134 _EGLDisplay *disp = _eglLookupDisplay(dpy);
135 struct drm_device *dev = (struct drm_device *)drv;
136 struct drm_screen *screen = NULL;
137 drmModeConnectorPtr connector = NULL;
138 drmModeResPtr res = NULL;
139 unsigned count_connectors = 0;
140 int num_screens = 0;
141 EGLint i;
142 int fd;
143
144 fd = drmOpen("i915", NULL);
145 if (fd < 0)
146 goto err_fd;
147
148 dev->drmFD = fd;
149 drm_get_device_id(dev);
150
151 dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL);
152 if (!dev->screen)
153 goto err_screen;
154 dev->winsys = dev->screen->winsys;
155
156 /* TODO HACK */
157 driInitExtensions(NULL, card_extensions, GL_FALSE);
158
159 drm_update_res(dev);
160 res = dev->res;
161 if (res)
162 count_connectors = res->count_connectors;
163 else
164 _eglLog(_EGL_WARNING, "Could not retrive kms information\n");
165
166 for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) {
167 connector = drmModeGetConnector(fd, res->connectors[i]);
168
169 if (!connector)
170 continue;
171
172 if (connector->connection != DRM_MODE_CONNECTED) {
173 drmModeFreeConnector(connector);
174 continue;
175 }
176
177 screen = malloc(sizeof(struct drm_screen));
178 memset(screen, 0, sizeof(*screen));
179 screen->connector = connector;
180 screen->connectorID = connector->connector_id;
181 _eglInitScreen(&screen->base);
182 _eglAddScreen(disp, &screen->base);
183 drm_add_modes_from_connector(&screen->base, connector);
184 drm_find_dpms(dev, screen);
185 dev->screens[num_screens++] = screen;
186 }
187 dev->count_screens = num_screens;
188
189 /* for now we only have one config */
190 _EGLConfig *config = calloc(1, sizeof(*config));
191 memset(config, 1, sizeof(*config));
192 _eglInitConfig(config, 1);
193 _eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
194 _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
195 _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
196 _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
197 _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
198 _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24);
199 _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
200 _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
201 _eglAddConfig(disp, config);
202
203 drv->Initialized = EGL_TRUE;
204
205 *major = 1;
206 *minor = 4;
207
208 return EGL_TRUE;
209
210 err_screen:
211 drmClose(fd);
212 err_fd:
213 return EGL_FALSE;
214 }
215
216 EGLBoolean
217 drm_terminate(_EGLDriver *drv, EGLDisplay dpy)
218 {
219 struct drm_device *dev = (struct drm_device *)drv;
220 struct drm_screen *screen;
221 int i = 0;
222
223 drmFreeVersion(dev->version);
224
225 for (i = 0; i < dev->count_screens; i++) {
226 screen = dev->screens[i];
227
228 if (screen->shown)
229 drm_takedown_shown_screen(drv, screen);
230
231 drmModeFreeProperty(screen->dpms);
232 drmModeFreeConnector(screen->connector);
233 _eglDestroyScreen(&screen->base);
234 dev->screens[i] = NULL;
235 }
236
237 dev->screen->destroy(dev->screen);
238 dev->winsys = NULL;
239 dev->api->destroy(dev->api);
240
241 drmClose(dev->drmFD);
242
243 _eglCleanupDisplay(_eglLookupDisplay(dpy));
244 free(dev);
245
246 return EGL_TRUE;
247 }