Add empty placeholder for eglCopyContextMESA
[mesa.git] / src / egl / main / eglcontext.c
1 #include <assert.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "eglconfig.h"
5 #include "eglcontext.h"
6 #include "egldriver.h"
7 #include "eglglobals.h"
8 #include "eglhash.h"
9 #include "eglsurface.h"
10
11
12 /**
13 * Initialize the given _EGLContext object to defaults.
14 */
15 void
16 _eglInitContext(_EGLContext *ctx)
17 {
18 /* just init to zero for now */
19 memset(ctx, 0, sizeof(_EGLContext));
20 }
21
22
23 /*
24 * Assign an EGLContext handle to the _EGLContext object then put it into
25 * the hash table.
26 */
27 void
28 _eglSaveContext(_EGLContext *ctx)
29 {
30 assert(ctx);
31 ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts);
32 _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx);
33 }
34
35
36 /**
37 * Remove the given _EGLContext object from the hash table.
38 */
39 void
40 _eglRemoveContext(_EGLContext *ctx)
41 {
42 _eglHashRemove(_eglGlobal.Contexts, ctx->Handle);
43 }
44
45
46 /**
47 * Return the _EGLContext object that corresponds to the given
48 * EGLContext handle.
49 */
50 _EGLContext *
51 _eglLookupContext(EGLContext ctx)
52 {
53 _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx);
54 return c;
55 }
56
57
58 /**
59 * Return the currently bound _EGLContext object, or NULL.
60 */
61 _EGLContext *
62 _eglGetCurrentContext(void)
63 {
64 /* XXX this should be per-thread someday */
65 return _eglGlobal.CurrentContext;
66 }
67
68
69 /**
70 * Just a placeholder/demo function. Real driver will never use this!
71 */
72 EGLContext
73 _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
74 {
75 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
76 if (!conf) {
77 _eglError(EGL_BAD_CONFIG, "eglCreateContext");
78 return EGL_NO_CONTEXT;
79 }
80
81 if (share_list != EGL_NO_CONTEXT) {
82 _EGLContext *shareCtx = _eglLookupContext(share_list);
83 if (!shareCtx) {
84 _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)");
85 return EGL_NO_CONTEXT;
86 }
87 }
88
89 return EGL_NO_CONTEXT;
90 }
91
92
93 /**
94 * Default fallback routine - drivers should usually override this.
95 */
96 EGLBoolean
97 _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
98 {
99 _EGLContext *context = _eglLookupContext(ctx);
100 if (context) {
101 _eglHashRemove(_eglGlobal.Contexts, ctx);
102 if (context->IsBound) {
103 context->DeletePending = EGL_TRUE;
104 }
105 else {
106 free(context);
107 }
108 return EGL_TRUE;
109 }
110 else {
111 _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
112 return EGL_TRUE;
113 }
114 }
115
116
117 EGLBoolean
118 _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
119 {
120 _EGLContext *c = _eglLookupContext(ctx);
121
122 (void) drv;
123 (void) dpy;
124
125 if (!c) {
126 _eglError(EGL_BAD_CONTEXT, "eglQueryContext");
127 return EGL_FALSE;
128 }
129
130 switch (attribute) {
131 case EGL_CONFIG_ID:
132 *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
133 return EGL_TRUE;
134 default:
135 _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
136 return EGL_FALSE;
137 }
138 }
139
140
141 /**
142 * Drivers will typically call this to do the error checking and
143 * update the various IsBound and DeletePending flags.
144 * Then, the driver will do its device-dependent Make-Current stuff.
145 */
146 EGLBoolean
147 _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, EGLSurface r, EGLContext context)
148 {
149 _EGLContext *ctx = _eglLookupContext(context);
150 _EGLSurface *draw = _eglLookupSurface(d);
151 _EGLSurface *read = _eglLookupSurface(r);
152
153 _EGLContext *oldContext = _eglGetCurrentContext();
154 _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW);
155 _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ);
156
157 /* error checking */
158 if (ctx) {
159 if (draw == NULL || read == NULL) {
160 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
161 return EGL_FALSE;
162 }
163 if (draw->Config != ctx->Config) {
164 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
165 return EGL_FALSE;
166 }
167 if (read->Config != ctx->Config) {
168 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
169 return EGL_FALSE;
170 }
171 }
172
173 /*
174 * check if the old context or surfaces need to be deleted
175 */
176 if (oldDrawSurface != NULL) {
177 oldDrawSurface->IsBound = EGL_FALSE;
178 if (oldDrawSurface->DeletePending) {
179 /* make sure we don't try to rebind a deleted surface */
180 if (draw == oldDrawSurface || draw == oldReadSurface) {
181 draw = NULL;
182 }
183 /* really delete surface now */
184 drv->DestroySurface(drv, dpy, oldDrawSurface->Handle);
185 }
186 }
187 if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) {
188 oldReadSurface->IsBound = EGL_FALSE;
189 if (oldReadSurface->DeletePending) {
190 /* make sure we don't try to rebind a deleted surface */
191 if (read == oldDrawSurface || read == oldReadSurface) {
192 read = NULL;
193 }
194 /* really delete surface now */
195 drv->DestroySurface(drv, dpy, oldReadSurface->Handle);
196 }
197 }
198 if (oldContext != NULL) {
199 oldContext->IsBound = EGL_FALSE;
200 if (oldContext->DeletePending) {
201 /* make sure we don't try to rebind a deleted context */
202 if (ctx == oldContext) {
203 ctx = NULL;
204 }
205 /* really delete context now */
206 drv->DestroyContext(drv, dpy, oldContext->Handle);
207 }
208 }
209
210 if (ctx) {
211 /* check read/draw again, in case we deleted them above */
212 if (draw == NULL || read == NULL) {
213 _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
214 return EGL_FALSE;
215 }
216 ctx->DrawSurface = draw;
217 ctx->ReadSurface = read;
218 ctx->IsBound = EGL_TRUE;
219 draw->IsBound = EGL_TRUE;
220 read->IsBound = EGL_TRUE;
221 }
222
223 _eglGlobal.CurrentContext = ctx;
224
225 return EGL_TRUE;
226 }
227
228
229 EGLBoolean
230 _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, unsigned long mask)
231 {
232 return EGL_FALSE;
233 }
234