egl: Support per-thread info.
[mesa.git] / src / egl / main / eglsurface.c
1 /**
2 * Surface-related functions.
3 */
4
5
6 #include <assert.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "eglcontext.h"
10 #include "eglconfig.h"
11 #include "egldriver.h"
12 #include "eglglobals.h"
13 #include "eglhash.h"
14 #include "egllog.h"
15 #include "eglsurface.h"
16
17
18 /**
19 * Do error check on parameters and initialize the given _EGLSurface object.
20 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
21 */
22 EGLBoolean
23 _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
24 _EGLSurface *surf, EGLint type, EGLConfig config,
25 const EGLint *attrib_list)
26 {
27 const char *func;
28 _EGLConfig *conf;
29 EGLint width = 0, height = 0, largest = 0;
30 EGLint texFormat = 0, texTarget = 0, mipmapTex = 0;
31 EGLint renderBuffer = EGL_BACK_BUFFER;
32 #ifdef EGL_VERSION_1_2
33 EGLint colorspace = EGL_COLORSPACE_sRGB;
34 EGLint alphaFormat = EGL_ALPHA_FORMAT_NONPRE;
35 #endif
36 EGLint i;
37
38 switch (type) {
39 case EGL_WINDOW_BIT:
40 func = "eglCreateWindowSurface";
41 break;
42 case EGL_PIXMAP_BIT:
43 func = "eglCreatePixmapSurface";
44 renderBuffer = EGL_SINGLE_BUFFER;
45 break;
46 case EGL_PBUFFER_BIT:
47 func = "eglCreatePBufferSurface";
48 break;
49 case EGL_SCREEN_BIT_MESA:
50 func = "eglCreateScreenSurface";
51 renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */
52 break;
53 default:
54 _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
55 return EGL_FALSE;
56 }
57
58 conf = _eglLookupConfig(drv, dpy, config);
59 if (!conf) {
60 _eglError(EGL_BAD_CONFIG, func);
61 return EGL_FALSE;
62 }
63
64 if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
65 /* The config can't be used to create a surface of this type */
66 _eglError(EGL_BAD_CONFIG, func);
67 return EGL_FALSE;
68 }
69
70 /*
71 * Parse attribute list. Different kinds of surfaces support different
72 * attributes.
73 */
74 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
75 switch (attrib_list[i]) {
76 case EGL_WIDTH:
77 if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
78 width = attrib_list[++i];
79 }
80 else {
81 _eglError(EGL_BAD_ATTRIBUTE, func);
82 return EGL_FALSE;
83 }
84 break;
85 case EGL_HEIGHT:
86 if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) {
87 height = attrib_list[++i];
88 }
89 else {
90 _eglError(EGL_BAD_ATTRIBUTE, func);
91 return EGL_FALSE;
92 }
93 break;
94 case EGL_LARGEST_PBUFFER:
95 if (type == EGL_PBUFFER_BIT) {
96 largest = attrib_list[++i];
97 }
98 else {
99 _eglError(EGL_BAD_ATTRIBUTE, func);
100 return EGL_FALSE;
101 }
102 break;
103 case EGL_TEXTURE_FORMAT:
104 if (type == EGL_PBUFFER_BIT) {
105 texFormat = attrib_list[++i];
106 }
107 else {
108 _eglError(EGL_BAD_ATTRIBUTE, func);
109 return EGL_FALSE;
110 }
111 break;
112 case EGL_TEXTURE_TARGET:
113 if (type == EGL_PBUFFER_BIT) {
114 texTarget = attrib_list[++i];
115 }
116 else {
117 _eglError(EGL_BAD_ATTRIBUTE, func);
118 return EGL_FALSE;
119 }
120 break;
121 case EGL_MIPMAP_TEXTURE:
122 if (type == EGL_PBUFFER_BIT) {
123 mipmapTex = attrib_list[++i];
124 }
125 else {
126 _eglError(EGL_BAD_ATTRIBUTE, func);
127 return EGL_FALSE;
128 }
129 break;
130 #ifdef EGL_VERSION_1_2
131 case EGL_RENDER_BUFFER:
132 if (type == EGL_WINDOW_BIT) {
133 renderBuffer = attrib_list[++i];
134 if (renderBuffer != EGL_BACK_BUFFER &&
135 renderBuffer != EGL_SINGLE_BUFFER) {
136 _eglError(EGL_BAD_ATTRIBUTE, func);
137 return EGL_FALSE;
138 }
139 }
140 else {
141 _eglError(EGL_BAD_ATTRIBUTE, func);
142 return EGL_FALSE;
143 }
144 break;
145 case EGL_COLORSPACE:
146 if (type == EGL_WINDOW_BIT ||
147 type == EGL_PBUFFER_BIT ||
148 type == EGL_PIXMAP_BIT) {
149 colorspace = attrib_list[++i];
150 if (colorspace != EGL_COLORSPACE_sRGB &&
151 colorspace != EGL_COLORSPACE_LINEAR) {
152 _eglError(EGL_BAD_ATTRIBUTE, func);
153 return EGL_FALSE;
154 }
155 }
156 else {
157 _eglError(EGL_BAD_ATTRIBUTE, func);
158 return EGL_FALSE;
159 }
160 break;
161 case EGL_ALPHA_FORMAT:
162 if (type == EGL_WINDOW_BIT ||
163 type == EGL_PBUFFER_BIT ||
164 type == EGL_PIXMAP_BIT) {
165 alphaFormat = attrib_list[++i];
166 if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE &&
167 alphaFormat != EGL_ALPHA_FORMAT_PRE) {
168 _eglError(EGL_BAD_ATTRIBUTE, func);
169 return EGL_FALSE;
170 }
171 }
172 else {
173 _eglError(EGL_BAD_ATTRIBUTE, func);
174 return EGL_FALSE;
175 }
176 break;
177
178 #endif /* EGL_VERSION_1_2 */
179 default:
180 _eglError(EGL_BAD_ATTRIBUTE, func);
181 return EGL_FALSE;
182 }
183 }
184
185 if (width < 0 || height < 0) {
186 _eglError(EGL_BAD_ATTRIBUTE, func);
187 return EGL_FALSE;
188 }
189
190 memset(surf, 0, sizeof(_EGLSurface));
191 surf->Config = conf;
192 surf->Type = type;
193 surf->Width = width;
194 surf->Height = height;
195 surf->TextureFormat = texFormat;
196 surf->TextureTarget = texTarget;
197 surf->MipmapTexture = mipmapTex;
198 surf->MipmapLevel = 0;
199 surf->SwapInterval = 0;
200 #ifdef EGL_VERSION_1_2
201 surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
202 surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
203 surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */
204 surf->AspectRatio = EGL_UNKNOWN; /* set by caller */
205 surf->RenderBuffer = renderBuffer;
206 surf->AlphaFormat = alphaFormat;
207 surf->Colorspace = colorspace;
208 #endif
209
210 return EGL_TRUE;
211 }
212
213
214 void
215 _eglSaveSurface(_EGLSurface *surf)
216 {
217 EGLuint key = _eglHashGenKey(_eglGlobal.Surfaces);
218 assert(surf);
219 assert(!surf->Handle);
220 surf->Handle = (EGLSurface) key;
221 assert(surf->Handle);
222 _eglHashInsert(_eglGlobal.Surfaces, key, surf);
223 }
224
225
226 void
227 _eglRemoveSurface(_EGLSurface *surf)
228 {
229 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle);
230 }
231
232
233
234 /**
235 * Return the public handle for an internal _EGLSurface.
236 * This is the inverse of _eglLookupSurface().
237 */
238 EGLSurface
239 _eglGetSurfaceHandle(_EGLSurface *surface)
240 {
241 if (surface)
242 return surface->Handle;
243 else
244 return EGL_NO_SURFACE;
245 }
246
247
248 /**
249 * Return the private _EGLSurface which corresponds to a public EGLSurface
250 * handle.
251 * This is the inverse of _eglGetSurfaceHandle().
252 */
253 _EGLSurface *
254 _eglLookupSurface(EGLSurface surf)
255 {
256 _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces,
257 (EGLuint) surf);
258 return c;
259 }
260
261
262 EGLBoolean
263 _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
264 {
265 /* Basically just do error checking here. Drivers have to do the
266 * actual buffer swap.
267 */
268 _EGLSurface *surface = _eglLookupSurface(draw);
269 if (surface == NULL) {
270 _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
271 return EGL_FALSE;
272 }
273 return EGL_TRUE;
274 }
275
276
277 EGLBoolean
278 _eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
279 NativePixmapType target)
280 {
281 /* copy surface to native pixmap */
282 /* All implementation burdon for this is in the device driver */
283 return EGL_FALSE;
284 }
285
286
287 EGLBoolean
288 _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
289 EGLint attribute, EGLint *value)
290 {
291 _EGLSurface *surface = _eglLookupSurface(surf);
292 if (surface == NULL) {
293 _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
294 return EGL_FALSE;
295 }
296 switch (attribute) {
297 case EGL_WIDTH:
298 *value = surface->Width;
299 return EGL_TRUE;
300 case EGL_HEIGHT:
301 *value = surface->Height;
302 return EGL_TRUE;
303 case EGL_CONFIG_ID:
304 *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
305 return EGL_TRUE;
306 case EGL_LARGEST_PBUFFER:
307 *value = drv->LargestPbuffer;
308 return EGL_TRUE;
309 case EGL_SURFACE_TYPE:
310 *value = surface->Type;
311 return EGL_TRUE;
312 #ifdef EGL_VERSION_1_1
313 case EGL_TEXTURE_FORMAT:
314 /* texture attributes: only for pbuffers, no error otherwise */
315 if (surface->Type == EGL_PBUFFER_BIT)
316 *value = surface->TextureFormat;
317 return EGL_TRUE;
318 case EGL_TEXTURE_TARGET:
319 if (surface->Type == EGL_PBUFFER_BIT)
320 *value = surface->TextureTarget;
321 return EGL_TRUE;
322 case EGL_MIPMAP_TEXTURE:
323 if (surface->Type == EGL_PBUFFER_BIT)
324 *value = surface->MipmapTexture;
325 return EGL_TRUE;
326 case EGL_MIPMAP_LEVEL:
327 if (surface->Type == EGL_PBUFFER_BIT)
328 *value = surface->MipmapLevel;
329 return EGL_TRUE;
330 #endif /* EGL_VERSION_1_1 */
331 #ifdef EGL_VERSION_1_2
332 case EGL_SWAP_BEHAVIOR:
333 *value = surface->SwapBehavior;
334 return EGL_TRUE;
335 case EGL_RENDER_BUFFER:
336 *value = surface->RenderBuffer;
337 return EGL_TRUE;
338 case EGL_PIXEL_ASPECT_RATIO:
339 *value = surface->AspectRatio;
340 return EGL_TRUE;
341 case EGL_HORIZONTAL_RESOLUTION:
342 *value = surface->HorizontalResolution;
343 return EGL_TRUE;
344 case EGL_VERTICAL_RESOLUTION:
345 *value = surface->VerticalResolution;
346 return EGL_TRUE;
347 case EGL_ALPHA_FORMAT:
348 *value = surface->AlphaFormat;
349 return EGL_TRUE;
350 case EGL_COLORSPACE:
351 *value = surface->Colorspace;
352 return EGL_TRUE;
353 #endif /* EGL_VERSION_1_2 */
354 default:
355 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
356 return EGL_FALSE;
357 }
358 }
359
360
361 /**
362 * Example function - drivers should do a proper implementation.
363 */
364 EGLSurface
365 _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
366 NativeWindowType window, const EGLint *attrib_list)
367 {
368 #if 0 /* THIS IS JUST EXAMPLE CODE */
369 _EGLSurface *surf;
370
371 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
372 if (!surf)
373 return EGL_NO_SURFACE;
374
375 if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
376 free(surf);
377 return EGL_NO_SURFACE;
378 }
379
380 _eglSaveSurface(surf);
381
382 return surf->Handle;
383 #endif
384 return EGL_NO_SURFACE;
385 }
386
387
388 /**
389 * Example function - drivers should do a proper implementation.
390 */
391 EGLSurface
392 _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
393 NativePixmapType pixmap, const EGLint *attrib_list)
394 {
395 #if 0 /* THIS IS JUST EXAMPLE CODE */
396 _EGLSurface *surf;
397
398 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
399 if (!surf)
400 return EGL_NO_SURFACE;
401
402 if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
403 free(surf);
404 return EGL_NO_SURFACE;
405 }
406
407 _eglSaveSurface(surf);
408
409 return surf->Handle;
410 #endif
411 return EGL_NO_SURFACE;
412 }
413
414
415 /**
416 * Example function - drivers should do a proper implementation.
417 */
418 EGLSurface
419 _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
420 const EGLint *attrib_list)
421 {
422 #if 0 /* THIS IS JUST EXAMPLE CODE */
423 _EGLSurface *surf;
424
425 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
426 if (!surf)
427 return EGL_NO_SURFACE;
428
429 if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
430 free(surf);
431 return EGL_NO_SURFACE;
432 }
433
434 _eglSaveSurface(surf);
435
436 return surf->Handle;
437 #endif
438 return EGL_NO_SURFACE;
439 }
440
441
442 /**
443 * Default fallback routine - drivers should usually override this.
444 */
445 EGLBoolean
446 _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
447 {
448 _EGLSurface *surf = _eglLookupSurface(surface);
449 if (surf) {
450 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
451 if (surf->IsBound) {
452 surf->DeletePending = EGL_TRUE;
453 }
454 else {
455 free(surf);
456 }
457 return EGL_TRUE;
458 }
459 else {
460 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
461 return EGL_FALSE;
462 }
463 }
464
465
466 /**
467 * Default fallback routine - drivers might override this.
468 */
469 EGLBoolean
470 _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
471 EGLint attribute, EGLint value)
472 {
473 _EGLSurface *surface = _eglLookupSurface(surf);
474
475 if (surface == NULL) {
476 _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib");
477 return EGL_FALSE;
478 }
479
480 switch (attribute) {
481 case EGL_MIPMAP_LEVEL:
482 surface->MipmapLevel = value;
483 break;
484 default:
485 _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib");
486 return EGL_FALSE;
487 }
488 return EGL_TRUE;
489 }
490
491
492 EGLBoolean
493 _eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
494 EGLint buffer)
495 {
496 /* Just do basic error checking and return success/fail.
497 * Drivers must implement the real stuff.
498 */
499 _EGLSurface *surface = _eglLookupSurface(surf);
500
501 if (!surface || surface->Type != EGL_PBUFFER_BIT) {
502 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
503 return EGL_FALSE;
504 }
505
506 if (surface->TextureFormat == EGL_NO_TEXTURE) {
507 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
508 return EGL_FALSE;
509 }
510
511 if (buffer != EGL_BACK_BUFFER) {
512 _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
513 return EGL_FALSE;
514 }
515
516 surface->BoundToTexture = EGL_TRUE;
517
518 return EGL_TRUE;
519 }
520
521
522 EGLBoolean
523 _eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
524 EGLint buffer)
525 {
526 /* Just do basic error checking and return success/fail.
527 * Drivers must implement the real stuff.
528 */
529 _EGLSurface *surface = _eglLookupSurface(surf);
530
531 if (!surface || surface->Type != EGL_PBUFFER_BIT) {
532 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
533 return EGL_FALSE;
534 }
535
536 if (surface->TextureFormat == EGL_NO_TEXTURE) {
537 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
538 return EGL_FALSE;
539 }
540
541 if (buffer != EGL_BACK_BUFFER) {
542 _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
543 return EGL_FALSE;
544 }
545
546 if (!surface->BoundToTexture) {
547 _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
548 return EGL_FALSE;
549 }
550
551 surface->BoundToTexture = EGL_FALSE;
552
553 return EGL_TRUE;
554 }
555
556
557 EGLBoolean
558 _eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
559 {
560 _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
561 if (surf == NULL) {
562 _eglError(EGL_BAD_SURFACE, "eglSwapInterval");
563 return EGL_FALSE;
564 }
565 surf->SwapInterval = interval;
566 return EGL_TRUE;
567 }
568
569
570 #ifdef EGL_VERSION_1_2
571
572 /**
573 * Example function - drivers should do a proper implementation.
574 */
575 EGLSurface
576 _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
577 EGLenum buftype, EGLClientBuffer buffer,
578 EGLConfig config, const EGLint *attrib_list)
579 {
580 if (buftype != EGL_OPENVG_IMAGE) {
581 _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
582 return EGL_NO_SURFACE;
583 }
584
585 return EGL_NO_SURFACE;
586 }
587
588 #endif /* EGL_VERSION_1_2 */