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