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