Redo _eglInitSurface() so it can be used with all surface types.
[mesa.git] / src / egl / main / eglsurface.c
1 /**
2 * Surface-related functions.
3 *
4 * See the eglcontext.c file for comments that also apply here.
5 */
6
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include "eglcontext.h"
12 #include "eglconfig.h"
13 #include "eglglobals.h"
14 #include "eglhash.h"
15 #include "egllog.h"
16 #include "eglsurface.h"
17
18
19 /**
20 * Do error check on parameters and initialize the given _EGLSurface object.
21 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
22 */
23 EGLBoolean
24 _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
25 _EGLSurface *surf, EGLint type, EGLConfig config,
26 const EGLint *attrib_list)
27 {
28 const char *func;
29 _EGLConfig *conf;
30 EGLint width = 0, height = 0, largest = 0;
31 EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
32 EGLint i;
33
34 switch (type) {
35 case EGL_WINDOW_BIT:
36 func = "eglCreateWindowSurface";
37 break;
38 case EGL_PIXMAP_BIT:
39 func = "eglCreatePixmapSurface";
40 break;
41 case EGL_PBUFFER_BIT:
42 func = "eglCreatePBufferSurface";
43 break;
44 case EGL_SCREEN_BIT_MESA:
45 func = "eglCreateScreenSurface";
46 break;
47 default:
48 _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
49 return EGL_FALSE;
50 }
51
52 conf = _eglLookupConfig(drv, dpy, config);
53 if (!conf) {
54 _eglError(EGL_BAD_CONFIG, func);
55 return EGL_FALSE;
56 }
57
58 /*
59 * Parse attribute list. Different kinds of surfaces support different
60 * attributes.
61 */
62 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
63 switch (attrib_list[i]) {
64 case EGL_WIDTH:
65 if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
66 width = attrib_list[++i];
67 }
68 else {
69 _eglError(EGL_BAD_ATTRIBUTE, func);
70 return EGL_FALSE;
71 }
72 break;
73 case EGL_HEIGHT:
74 if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
75 height = attrib_list[++i];
76 }
77 else {
78 _eglError(EGL_BAD_ATTRIBUTE, func);
79 return EGL_FALSE;
80 }
81 break;
82 case EGL_LARGEST_PBUFFER:
83 if (type == EGL_PBUFFER_BIT) {
84 largest = attrib_list[++i];
85 }
86 else {
87 _eglError(EGL_BAD_ATTRIBUTE, func);
88 return EGL_FALSE;
89 }
90 break;
91 case EGL_TEXTURE_FORMAT:
92 if (type == EGL_PBUFFER_BIT) {
93 texFormat = attrib_list[++i];
94 }
95 else {
96 _eglError(EGL_BAD_ATTRIBUTE, func);
97 return EGL_FALSE;
98 }
99 break;
100 case EGL_TEXTURE_TARGET:
101 if (type == EGL_PBUFFER_BIT) {
102 texTarget = attrib_list[++i];
103 }
104 else {
105 _eglError(EGL_BAD_ATTRIBUTE, func);
106 return EGL_FALSE;
107 }
108 break;
109 case EGL_MIPMAP_TEXTURE:
110 if (type == EGL_PBUFFER_BIT) {
111 mipmapTex = attrib_list[++i];
112 }
113 else {
114 _eglError(EGL_BAD_ATTRIBUTE, func);
115 return EGL_FALSE;
116 }
117 break;
118 default:
119 _eglError(EGL_BAD_ATTRIBUTE, func);
120 return EGL_FALSE;
121 }
122 }
123
124 if (width <= 0 || height <= 0) {
125 _eglError(EGL_BAD_ATTRIBUTE, func);
126 return EGL_FALSE;
127 }
128
129 memset(surf, 0, sizeof(_EGLSurface));
130 surf->Config = conf;
131 surf->Type = type;
132 surf->Width = width;
133 surf->Height = height;
134 surf->TextureFormat = texFormat;
135 surf->TextureTarget = texTarget;
136 surf->MipmapTexture = mipmapTex;
137 surf->MipmapLevel = 0;
138 surf->SwapInterval = 0;
139
140 return EGL_TRUE;
141 }
142
143
144 void
145 _eglSaveSurface(_EGLSurface *surf)
146 {
147 assert(surf);
148 assert(!surf->Handle);
149 surf->Handle = _eglHashGenKey(_eglGlobal.Contexts);
150 assert(surf->Handle);
151 _eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf);
152 }
153
154
155 void
156 _eglRemoveSurface(_EGLSurface *surf)
157 {
158 _eglHashRemove(_eglGlobal.Surfaces, surf->Handle);
159 }
160
161
162 _EGLSurface *
163 _eglLookupSurface(EGLSurface surf)
164 {
165 _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf);
166 return c;
167 }
168
169
170 _EGLSurface *
171 _eglGetCurrentSurface(EGLint readdraw)
172 {
173 _EGLContext *ctx = _eglGetCurrentContext();
174 if (ctx) {
175 switch (readdraw) {
176 case EGL_DRAW:
177 return ctx->DrawSurface;
178 case EGL_READ:
179 return ctx->ReadSurface;
180 default:
181 return NULL;
182 }
183 }
184 return NULL;
185 }
186
187
188 EGLBoolean
189 _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
190 {
191 /* Basically just do error checking here. Drivers have to do the
192 * actual buffer swap.
193 */
194 _EGLContext *context = _eglGetCurrentContext();
195 _EGLSurface *surface = _eglLookupSurface(draw);
196 if (context && context->DrawSurface != surface) {
197 _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
198 return EGL_FALSE;
199 }
200 if (surface == NULL) {
201 _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
202 return EGL_FALSE;
203 }
204 return EGL_TRUE;
205 }
206
207
208 EGLBoolean
209 _eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
210 NativePixmapType target)
211 {
212 /* copy surface to native pixmap */
213 /* All implementation burdon for this is in the device driver */
214 return EGL_FALSE;
215 }
216
217
218 EGLBoolean
219 _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
220 EGLint attribute, EGLint *value)
221 {
222 _EGLSurface *surface = _eglLookupSurface(surf);
223 if (surface == NULL) {
224 _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
225 return EGL_FALSE;
226 }
227 switch (attribute) {
228 case EGL_WIDTH:
229 *value = surface->Width;
230 return EGL_TRUE;
231 case EGL_HEIGHT:
232 *value = surface->Height;
233 return EGL_TRUE;
234 case EGL_CONFIG_ID:
235 *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
236 return EGL_TRUE;
237 case EGL_TEXTURE_FORMAT:
238 /* texture attributes: only for pbuffers, no error otherwise */
239 if (surface->Type == EGL_PBUFFER_BIT)
240 *value = surface->TextureFormat;
241 return EGL_TRUE;
242 case EGL_TEXTURE_TARGET:
243 if (surface->Type == EGL_PBUFFER_BIT)
244 *value = surface->TextureTarget;
245 return EGL_TRUE;
246 case EGL_MIPMAP_TEXTURE:
247 if (surface->Type == EGL_PBUFFER_BIT)
248 *value = surface->MipmapTexture;
249 return EGL_TRUE;
250 case EGL_MIPMAP_LEVEL:
251 if (surface->Type == EGL_PBUFFER_BIT)
252 *value = surface->MipmapLevel;
253 return EGL_TRUE;
254 case EGL_SURFACE_TYPE:
255 *value = surface->Type;
256 return EGL_TRUE;
257 default:
258 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
259 return EGL_FALSE;
260 }
261 }
262
263
264 /**
265 * Example function - drivers should do a proper implementation.
266 */
267 EGLSurface
268 _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
269 NativeWindowType window, const EGLint *attrib_list)
270 {
271 #if 0 /* THIS IS JUST EXAMPLE CODE */
272 _EGLSurface *surf;
273
274 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
275 if (!surf)
276 return EGL_NO_SURFACE;
277
278 if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
279 free(surf);
280 return EGL_NO_SURFACE;
281 }
282
283 _eglSaveSurface(surf);
284
285 return surf->Handle;
286 #endif
287 return EGL_NO_SURFACE;
288 }
289
290
291 /**
292 * Example function - drivers should do a proper implementation.
293 */
294 EGLSurface
295 _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
296 NativePixmapType pixmap, const EGLint *attrib_list)
297 {
298 #if 0 /* THIS IS JUST EXAMPLE CODE */
299 _EGLSurface *surf;
300
301 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
302 if (!surf)
303 return EGL_NO_SURFACE;
304
305 if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
306 free(surf);
307 return EGL_NO_SURFACE;
308 }
309
310 _eglSaveSurface(surf);
311
312 return surf->Handle;
313 #endif
314 return EGL_NO_SURFACE;
315 }
316
317
318 /**
319 * Example function - drivers should do a proper implementation.
320 */
321 EGLSurface
322 _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
323 const EGLint *attrib_list)
324 {
325 #if 0 /* THIS IS JUST EXAMPLE CODE */
326 _EGLSurface *surf;
327
328 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
329 if (!surf)
330 return EGL_NO_SURFACE;
331
332 if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
333 free(surf);
334 return EGL_NO_SURFACE;
335 }
336
337 _eglSaveSurface(surf);
338
339 return surf->Handle;
340 #endif
341 return EGL_NO_SURFACE;
342 }
343
344
345 /**
346 * Default fallback routine - drivers should usually override this.
347 */
348 EGLBoolean
349 _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
350 {
351 _EGLSurface *surf = _eglLookupSurface(surface);
352 if (surf) {
353 _eglHashRemove(_eglGlobal.Surfaces, surface);
354 if (surf->IsBound) {
355 surf->DeletePending = EGL_TRUE;
356 }
357 else {
358 free(surf);
359 }
360 return EGL_TRUE;
361 }
362 else {
363 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
364 return EGL_FALSE;
365 }
366 }
367
368
369 /**
370 * Default fallback routine - drivers might override this.
371 */
372 EGLBoolean
373 _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value)
374 {
375 _EGLSurface *surface = _eglLookupSurface(surf);
376
377 if (surface == NULL) {
378 _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib");
379 return EGL_FALSE;
380 }
381
382 switch (attribute) {
383 case EGL_MIPMAP_LEVEL:
384 surface->MipmapLevel = value;
385 break;
386 default:
387 _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib");
388 return EGL_FALSE;
389 }
390 return EGL_TRUE;
391 }
392
393
394 EGLBoolean
395 _eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
396 {
397 /* XXX unfinished */
398 return EGL_FALSE;
399 }
400
401
402 EGLBoolean
403 _eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
404 {
405 /* XXX unfinished */
406 return EGL_FALSE;
407 }
408
409
410 EGLBoolean
411 _eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
412 {
413 _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
414 if (surf == NULL) {
415 _eglError(EGL_BAD_SURFACE, "eglSwapInterval");
416 return EGL_FALSE;
417 }
418 surf->SwapInterval = interval;
419 return EGL_TRUE;
420 }