Merge commit 'nha/r300-compiler-gallium'
[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) _eglUIntToPointer(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 EGLuint key = _eglPointerToUInt((void *) dpy->Handle);
70 _eglHashRemove(_eglGlobal.Displays, key);
71 dpy->Handle = EGL_NO_DISPLAY;
72 }
73
74
75 /**
76 * Return the handle of a linked display, or EGL_NO_DISPLAY.
77 */
78 EGLDisplay
79 _eglGetDisplayHandle(_EGLDisplay *display)
80 {
81 if (display)
82 return display->Handle;
83 else
84 return EGL_NO_DISPLAY;
85 }
86
87
88 /**
89 * Lookup a handle to find the linked display.
90 * Return NULL if the handle has no corresponding linked display.
91 */
92 _EGLDisplay *
93 _eglLookupDisplay(EGLDisplay dpy)
94 {
95 EGLuint key = _eglPointerToUInt((void *) dpy);
96 return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key);
97 }
98
99
100 /**
101 * Find the display corresponding to the specified native display id in all
102 * linked displays.
103 */
104 _EGLDisplay *
105 _eglFindDisplay(NativeDisplayType nativeDisplay)
106 {
107 EGLuint key = _eglHashFirstEntry(_eglGlobal.Displays);
108
109 /* Walk the hash table. Should switch to list if it is a problem. */
110 while (key) {
111 _EGLDisplay *dpy = (_EGLDisplay *)
112 _eglHashLookup(_eglGlobal.Displays, key);
113 assert(dpy);
114
115 if (dpy->NativeDisplay == nativeDisplay)
116 return dpy;
117 key = _eglHashNextEntry(_eglGlobal.Displays, key);
118 }
119
120 return NULL;
121 }
122
123
124 /**
125 * Destroy the contexts and surfaces that are linked to the display.
126 */
127 void
128 _eglReleaseDisplayResources(_EGLDriver *drv, EGLDisplay dpy)
129 {
130 _EGLDisplay *display;
131 _EGLContext *contexts;
132 _EGLSurface *surfaces;
133
134 display = _eglLookupDisplay(dpy);
135 if (!display)
136 return;
137 contexts = display->ContextList;
138 surfaces = display->SurfaceList;
139
140 while (contexts) {
141 EGLContext handle = _eglGetContextHandle(contexts);
142 contexts = contexts->Next;
143 drv->API.DestroyContext(drv, dpy, handle);
144 }
145 assert(!display->ContextList);
146
147 while (surfaces) {
148 EGLSurface handle = _eglGetSurfaceHandle(surfaces);
149 surfaces = surfaces->Next;
150 drv->API.DestroySurface(drv, dpy, handle);
151 }
152 assert(!display->SurfaceList);
153 }
154
155
156 /**
157 * Free all the data hanging of an _EGLDisplay object, but not
158 * the object itself.
159 */
160 void
161 _eglCleanupDisplay(_EGLDisplay *disp)
162 {
163 EGLint i;
164
165 for (i = 0; i < disp->NumConfigs; i++) {
166 free(disp->Configs[i]);
167 }
168 free(disp->Configs);
169 disp->Configs = NULL;
170
171 /* XXX incomplete */
172
173 free((void *) disp->DriverName);
174 disp->DriverName = NULL;
175
176 /* driver deletes the _EGLDisplay object */
177 }
178
179
180 /**
181 * Link a context to a display and return the handle of the link.
182 * The handle can be passed to client directly.
183 */
184 EGLContext
185 _eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy)
186 {
187 ctx->Display = dpy;
188 ctx->Next = dpy->ContextList;
189 dpy->ContextList = ctx;
190 return (EGLContext) ctx;
191 }
192
193
194 /**
195 * Unlink a linked context from its display.
196 * Accessing an unlinked context should generate EGL_BAD_CONTEXT error.
197 */
198 void
199 _eglUnlinkContext(_EGLContext *ctx)
200 {
201 _EGLContext *prev;
202
203 prev = ctx->Display->ContextList;
204 if (prev != ctx) {
205 while (prev) {
206 if (prev->Next == ctx)
207 break;
208 prev = prev->Next;
209 }
210 assert(prev);
211 prev->Next = ctx->Next;
212 }
213 else {
214 ctx->Display->ContextList = ctx->Next;
215 }
216
217 ctx->Next = NULL;
218 ctx->Display = NULL;
219 }
220
221
222 /**
223 * Return the handle of a linked context, or EGL_NO_CONTEXT.
224 */
225 EGLContext
226 _eglGetContextHandle(_EGLContext *ctx)
227 {
228 return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT);
229 }
230
231
232 /**
233 * Lookup a handle to find the linked context.
234 * Return NULL if the handle has no corresponding linked context.
235 */
236 _EGLContext *
237 _eglLookupContext(EGLContext ctx)
238 {
239 _EGLContext *context = (_EGLContext *) ctx;
240 return (context && context->Display) ? context : NULL;
241 }
242
243
244 /**
245 * Link a surface to a display and return the handle of the link.
246 * The handle can be passed to client directly.
247 */
248 EGLSurface
249 _eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy)
250 {
251 EGLuint key;
252
253 surf->Display = dpy;
254 surf->Next = dpy->SurfaceList;
255 dpy->SurfaceList = surf;
256
257 key = _eglHashGenKey(_eglGlobal.Surfaces);
258 assert(key);
259 _eglHashInsert(_eglGlobal.Surfaces, key, surf);
260
261 surf->Handle = (EGLSurface) _eglUIntToPointer(key);
262 return surf->Handle;
263 }
264
265
266 /**
267 * Unlink a linked surface from its display.
268 * Accessing an unlinked surface should generate EGL_BAD_SURFACE error.
269 */
270 void
271 _eglUnlinkSurface(_EGLSurface *surf)
272 {
273 _EGLSurface *prev;
274 EGLuint key = _eglPointerToUInt((void *) surf->Handle);
275
276 _eglHashRemove(_eglGlobal.Surfaces, key);
277 surf->Handle = EGL_NO_SURFACE;
278
279 prev = surf->Display->SurfaceList;
280 if (prev != surf) {
281 while (prev) {
282 if (prev->Next == surf)
283 break;
284 prev = prev->Next;
285 }
286 assert(prev);
287 prev->Next = surf->Next;
288 }
289 else {
290 prev = NULL;
291 surf->Display->SurfaceList = surf->Next;
292 }
293
294 surf->Next = NULL;
295 surf->Display = NULL;
296 }
297
298
299 /**
300 * Return the handle of a linked surface, or EGL_NO_SURFACE.
301 */
302 EGLSurface
303 _eglGetSurfaceHandle(_EGLSurface *surface)
304 {
305 if (surface)
306 return surface->Handle;
307 else
308 return EGL_NO_SURFACE;
309 }
310
311
312 /**
313 * Lookup a handle to find the linked surface.
314 * Return NULL if the handle has no corresponding linked surface.
315 */
316 _EGLSurface *
317 _eglLookupSurface(EGLSurface surf)
318 {
319 EGLuint key = _eglPointerToUInt((void *) surf);
320 return (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, key);
321 }