Merge branch 'mesa_7_5_branch'
[mesa.git] / src / egl / main / egldisplay.c
1
2 /**
3 * Functions related to EGLDisplay.
4 */
5
6 #include <assert.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "eglcontext.h"
10 #include "eglsurface.h"
11 #include "egldisplay.h"
12 #include "egldriver.h"
13 #include "eglglobals.h"
14 #include "eglhash.h"
15 #include "eglstring.h"
16
17
18 /**
19 * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
20 * We'll also try to determine the device driver name at this time.
21 *
22 * Note that nativeDisplay may be an X Display ptr, or a string.
23 */
24 _EGLDisplay *
25 _eglNewDisplay(NativeDisplayType nativeDisplay)
26 {
27 _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
28 if (dpy) {
29 dpy->NativeDisplay = nativeDisplay;
30 #if defined(_EGL_PLATFORM_X)
31 dpy->Xdpy = (Display *) nativeDisplay;
32 #endif
33
34 dpy->DriverName = _eglChooseDriver(dpy);
35 if (!dpy->DriverName) {
36 free(dpy);
37 return NULL;
38 }
39 }
40 return dpy;
41 }
42
43
44 /**
45 * Link a display to itself and return the handle of the link.
46 * The handle can be passed to client directly.
47 */
48 EGLDisplay
49 _eglLinkDisplay(_EGLDisplay *dpy)
50 {
51 EGLuint key;
52 key = _eglHashGenKey(_eglGlobal.Displays);
53 assert(key);
54 /* "link" the display to the hash table */
55 _eglHashInsert(_eglGlobal.Displays, key, dpy);
56 dpy->Handle = (EGLDisplay) key;
57
58 return dpy->Handle;
59 }
60
61
62 /**
63 * Unlink a linked display from itself.
64 * Accessing an unlinked display should generate EGL_BAD_DISPLAY error.
65 */
66 void
67 _eglUnlinkDisplay(_EGLDisplay *dpy)
68 {
69 _eglHashRemove(_eglGlobal.Displays, (EGLuint) dpy->Handle);
70 dpy->Handle = EGL_NO_DISPLAY;
71 }
72
73
74 /**
75 * Return the handle of a linked display, or EGL_NO_DISPLAY.
76 */
77 EGLDisplay
78 _eglGetDisplayHandle(_EGLDisplay *display)
79 {
80 if (display)
81 return display->Handle;
82 else
83 return EGL_NO_DISPLAY;
84 }
85
86
87 /**
88 * Lookup a handle to find the linked display.
89 * Return NULL if the handle has no corresponding linked display.
90 */
91 _EGLDisplay *
92 _eglLookupDisplay(EGLDisplay dpy)
93 {
94 EGLuint key = (EGLuint) dpy;
95 return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key);
96 }
97
98
99 /**
100 * Find the display corresponding to the specified native display id in all
101 * linked displays.
102 */
103 _EGLDisplay *
104 _eglFindDisplay(NativeDisplayType nativeDisplay)
105 {
106 EGLuint key = _eglHashFirstEntry(_eglGlobal.Displays);
107
108 /* Walk the hash table. Should switch to list if it is a problem. */
109 while (key) {
110 _EGLDisplay *dpy = (_EGLDisplay *)
111 _eglHashLookup(_eglGlobal.Displays, key);
112 assert(dpy);
113
114 if (dpy->NativeDisplay == nativeDisplay)
115 return dpy;
116 key = _eglHashNextEntry(_eglGlobal.Displays, key);
117 }
118
119 return NULL;
120 }
121
122
123 /**
124 * Destroy the contexts and surfaces that are linked to the display.
125 */
126 void
127 _eglReleaseDisplayResources(_EGLDriver *drv, EGLDisplay dpy)
128 {
129 _EGLDisplay *display;
130 _EGLContext *contexts;
131 _EGLSurface *surfaces;
132
133 display = _eglLookupDisplay(dpy);
134 if (!display)
135 return;
136 contexts = display->ContextList;
137 surfaces = display->SurfaceList;
138
139 while (contexts) {
140 EGLContext handle = _eglGetContextHandle(contexts);
141 contexts = contexts->Next;
142 drv->API.DestroyContext(drv, dpy, handle);
143 }
144 assert(!display->ContextList);
145
146 while (surfaces) {
147 EGLSurface handle = _eglGetSurfaceHandle(surfaces);
148 surfaces = surfaces->Next;
149 drv->API.DestroySurface(drv, dpy, handle);
150 }
151 assert(!display->SurfaceList);
152 }
153
154
155 /**
156 * Free all the data hanging of an _EGLDisplay object, but not
157 * the object itself.
158 */
159 void
160 _eglCleanupDisplay(_EGLDisplay *disp)
161 {
162 EGLint i;
163
164 for (i = 0; i < disp->NumConfigs; i++) {
165 free(disp->Configs[i]);
166 }
167 free(disp->Configs);
168 disp->Configs = NULL;
169
170 /* XXX incomplete */
171
172 free((void *) disp->DriverName);
173 disp->DriverName = NULL;
174
175 /* driver deletes the _EGLDisplay object */
176 }
177
178
179 /**
180 * Link a context to a display and return the handle of the link.
181 * The handle can be passed to client directly.
182 */
183 EGLContext
184 _eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
185 {
186 ctx->Display = dpy;
187 ctx->Next = dpy->ContextList;
188 dpy->ContextList = ctx;
189 return (EGLContext) ctx;
190 }
191
192
193 /**
194 * Unlink a linked context from its display.
195 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
196 */
197 void
198 _eglUnlinkContext(_EGLContext *ctx)
199 {
200 _EGLContext *prev;
201
202 prev = ctx->Display->ContextList;
203 if (prev != ctx) {
204 while (prev) {
205 if (prev->Next == ctx)
206 break;
207 prev = prev->Next;
208 }
209 assert(prev);
210 prev->Next = ctx->Next;
211 }
212 else {
213 ctx->Display->ContextList = ctx->Next;
214 }
215
216 ctx->Next = NULL;
217 ctx->Display = NULL;
218 }
219
220
221 /**
222 * Return the handle of a linked context, or EGL_NO_CONTEXT.
223 */
224 EGLContext
225 _eglGetContextHandle(_EGLContext *ctx)
226 {
227 return (EGLContext) (ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT;
228 }
229
230
231 /**
232 * Lookup a handle to find the linked context.
233 * Return NULL if the handle has no corresponding linked context.
234 */
235 _EGLContext *
236 _eglLookupContext(EGLContext ctx)
237 {
238 _EGLContext *context = (_EGLContext *) ctx;
239 return (context && context->Display) ? context : NULL;
240 }
241
242
243 /**
244 * Link a surface to a display and return the handle of the link.
245 * The handle can be passed to client directly.
246 */
247 EGLSurface
248 _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
249 {
250 EGLuint key;
251
252 surf->Display = dpy;
253 surf->Next = dpy->SurfaceList;
254 dpy->SurfaceList = surf;
255
256 key = _eglHashGenKey(_eglGlobal.Surfaces);
257 assert(key);
258 _eglHashInsert(_eglGlobal.Surfaces, key, surf);
259
260 surf->Handle = (EGLSurface) key;
261 return surf->Handle;
262 }
263
264
265 /**
266 * Unlink a linked surface from its display.
267 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
268 */
269 void
270 _eglUnlinkSurface(_EGLSurface *surf)
271 {
272 _EGLSurface *prev;
273
274 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle);
275 surf->Handle = EGL_NO_SURFACE;
276
277 prev = surf->Display->SurfaceList;
278 if (prev != surf) {
279 while (prev) {
280 if (prev->Next == surf)
281 break;
282 prev = prev->Next;
283 }
284 assert(prev);
285 prev->Next = surf->Next;
286 }
287 else {
288 prev = NULL;
289 surf->Display->SurfaceList = surf->Next;
290 }
291
292 surf->Next = NULL;
293 surf->Display = NULL;
294 }
295
296
297 /**
298 * Return the handle of a linked surface, or EGL_NO_SURFACE.
299 */
300 EGLSurface
301 _eglGetSurfaceHandle(_EGLSurface *surface)
302 {
303 if (surface)
304 return surface->Handle;
305 else
306 return EGL_NO_SURFACE;
307 }
308
309
310 /**
311 * Lookup a handle to find the linked surface.
312 * Return NULL if the handle has no corresponding linked surface.
313 */
314 _EGLSurface *
315 _eglLookupSurface(EGLSurface surf)
316 {
317 _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces,
318 (EGLuint) surf);
319 return c;
320 }