Merge branch 'gallium-drm-driver-drescriptor'
[mesa.git] / src / egl / main / egldisplay.c
1 /**
2 * Functions related to EGLDisplay.
3 */
4
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include "eglcontext.h"
9 #include "eglsurface.h"
10 #include "egldisplay.h"
11 #include "egldriver.h"
12 #include "eglglobals.h"
13 #include "eglmutex.h"
14 #include "egllog.h"
15
16
17 /**
18 * Finish display management.
19 */
20 void
21 _eglFiniDisplay(void)
22 {
23 _EGLDisplay *dpyList, *dpy;
24
25 /* atexit function is called with global mutex locked */
26 dpyList = _eglGlobal.DisplayList;
27 while (dpyList) {
28 EGLint i;
29
30 /* pop list head */
31 dpy = dpyList;
32 dpyList = dpyList->Next;
33
34 for (i = 0; i < _EGL_NUM_RESOURCES; i++) {
35 if (dpy->ResourceLists[i]) {
36 _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy);
37 break;
38 }
39 }
40
41 free(dpy);
42 }
43 _eglGlobal.DisplayList = NULL;
44 }
45
46
47 /**
48 * Find the display corresponding to the specified native display, or create a
49 * new one.
50 */
51 _EGLDisplay *
52 _eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
53 {
54 _EGLDisplay *dpy;
55
56 if (plat == _EGL_INVALID_PLATFORM)
57 return NULL;
58
59 _eglLockMutex(_eglGlobal.Mutex);
60
61 /* search the display list first */
62 dpy = _eglGlobal.DisplayList;
63 while (dpy) {
64 if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
65 break;
66 dpy = dpy->Next;
67 }
68
69 /* create a new display */
70 if (!dpy) {
71 dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
72 if (dpy) {
73 _eglInitMutex(&dpy->Mutex);
74 dpy->Platform = plat;
75 dpy->PlatformDisplay = plat_dpy;
76
77 /* add to the display list */
78 dpy->Next = _eglGlobal.DisplayList;
79 _eglGlobal.DisplayList = dpy;
80 }
81 }
82
83 _eglUnlockMutex(_eglGlobal.Mutex);
84
85 return dpy;
86 }
87
88
89 /**
90 * Destroy the contexts and surfaces that are linked to the display.
91 */
92 void
93 _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
94 {
95 _EGLResource *list;
96
97 list = display->ResourceLists[_EGL_RESOURCE_CONTEXT];
98 while (list) {
99 _EGLContext *ctx = (_EGLContext *) list;
100 list = list->Next;
101
102 _eglUnlinkContext(ctx);
103 drv->API.DestroyContext(drv, display, ctx);
104 }
105 assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]);
106
107 list = display->ResourceLists[_EGL_RESOURCE_SURFACE];
108 while (list) {
109 _EGLSurface *surf = (_EGLSurface *) list;
110 list = list->Next;
111
112 _eglUnlinkSurface(surf);
113 drv->API.DestroySurface(drv, display, surf);
114 }
115 assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]);
116 }
117
118
119 /**
120 * Free all the data hanging of an _EGLDisplay object, but not
121 * the object itself.
122 */
123 void
124 _eglCleanupDisplay(_EGLDisplay *disp)
125 {
126 EGLint i;
127
128 if (disp->Configs) {
129 for (i = 0; i < disp->NumConfigs; i++)
130 free(disp->Configs[i]);
131 free(disp->Configs);
132 disp->Configs = NULL;
133 disp->NumConfigs = 0;
134 disp->MaxConfigs = 0;
135 }
136
137 /* XXX incomplete */
138 }
139
140
141 /**
142 * Return EGL_TRUE if the given handle is a valid handle to a display.
143 */
144 EGLBoolean
145 _eglCheckDisplayHandle(EGLDisplay dpy)
146 {
147 _EGLDisplay *cur;
148
149 _eglLockMutex(_eglGlobal.Mutex);
150 cur = _eglGlobal.DisplayList;
151 while (cur) {
152 if (cur == (_EGLDisplay *) dpy)
153 break;
154 cur = cur->Next;
155 }
156 _eglUnlockMutex(_eglGlobal.Mutex);
157 return (cur != NULL);
158 }
159
160
161 /**
162 * Return EGL_TRUE if the given resource is valid. That is, the display does
163 * own the resource.
164 */
165 EGLBoolean
166 _eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy)
167 {
168 _EGLResource *list = dpy->ResourceLists[type];
169
170 if (!res)
171 return EGL_FALSE;
172
173 while (list) {
174 if (res == (void *) list) {
175 assert(list->Display == dpy);
176 break;
177 }
178 list = list->Next;
179 }
180
181 return (list != NULL);
182 }
183
184
185 /**
186 * Link a resource to a display.
187 */
188 void
189 _eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy)
190 {
191 assert(!res->Display || res->Display == dpy);
192
193 res->Display = dpy;
194 res->IsLinked = EGL_TRUE;
195 res->Next = dpy->ResourceLists[type];
196 dpy->ResourceLists[type] = res;
197 }
198
199
200 /**
201 * Unlink a linked resource from its display.
202 */
203 void
204 _eglUnlinkResource(_EGLResource *res, _EGLResourceType type)
205 {
206 _EGLResource *prev;
207
208 prev = res->Display->ResourceLists[type];
209 if (prev != res) {
210 while (prev) {
211 if (prev->Next == res)
212 break;
213 prev = prev->Next;
214 }
215 assert(prev);
216 prev->Next = res->Next;
217 }
218 else {
219 res->Display->ResourceLists[type] = res->Next;
220 }
221
222 res->Next = NULL;
223 /* do not reset res->Display */
224 res->IsLinked = EGL_FALSE;
225 }