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