Merge commit 'origin/master' into gallium-0.2
[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 _EGLSurface *
263 _eglGetCurrentSurface(EGLint readdraw)
264 {
265 _EGLContext *ctx = _eglGetCurrentContext();
266 if (ctx) {
267 switch (readdraw) {
268 case EGL_DRAW:
269 return ctx->DrawSurface;
270 case EGL_READ:
271 return ctx->ReadSurface;
272 default:
273 return NULL;
274 }
275 }
276 return NULL;
277 }
278
279
280 EGLBoolean
281 _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
282 {
283 /* Basically just do error checking here. Drivers have to do the
284 * actual buffer swap.
285 */
286 _EGLSurface *surface = _eglLookupSurface(draw);
287 if (surface == NULL) {
288 _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
289 return EGL_FALSE;
290 }
291 return EGL_TRUE;
292 }
293
294
295 EGLBoolean
296 _eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
297 NativePixmapType target)
298 {
299 /* copy surface to native pixmap */
300 /* All implementation burdon for this is in the device driver */
301 return EGL_FALSE;
302 }
303
304
305 EGLBoolean
306 _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
307 EGLint attribute, EGLint *value)
308 {
309 _EGLSurface *surface = _eglLookupSurface(surf);
310 if (surface == NULL) {
311 _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
312 return EGL_FALSE;
313 }
314 switch (attribute) {
315 case EGL_WIDTH:
316 *value = surface->Width;
317 return EGL_TRUE;
318 case EGL_HEIGHT:
319 *value = surface->Height;
320 return EGL_TRUE;
321 case EGL_CONFIG_ID:
322 *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
323 return EGL_TRUE;
324 case EGL_LARGEST_PBUFFER:
325 *value = drv->LargestPbuffer;
326 return EGL_TRUE;
327 case EGL_SURFACE_TYPE:
328 *value = surface->Type;
329 return EGL_TRUE;
330 #ifdef EGL_VERSION_1_1
331 case EGL_TEXTURE_FORMAT:
332 /* texture attributes: only for pbuffers, no error otherwise */
333 if (surface->Type == EGL_PBUFFER_BIT)
334 *value = surface->TextureFormat;
335 return EGL_TRUE;
336 case EGL_TEXTURE_TARGET:
337 if (surface->Type == EGL_PBUFFER_BIT)
338 *value = surface->TextureTarget;
339 return EGL_TRUE;
340 case EGL_MIPMAP_TEXTURE:
341 if (surface->Type == EGL_PBUFFER_BIT)
342 *value = surface->MipmapTexture;
343 return EGL_TRUE;
344 case EGL_MIPMAP_LEVEL:
345 if (surface->Type == EGL_PBUFFER_BIT)
346 *value = surface->MipmapLevel;
347 return EGL_TRUE;
348 #endif /* EGL_VERSION_1_1 */
349 #ifdef EGL_VERSION_1_2
350 case EGL_SWAP_BEHAVIOR:
351 *value = surface->SwapBehavior;
352 return EGL_TRUE;
353 case EGL_RENDER_BUFFER:
354 *value = surface->RenderBuffer;
355 return EGL_TRUE;
356 case EGL_PIXEL_ASPECT_RATIO:
357 *value = surface->AspectRatio;
358 return EGL_TRUE;
359 case EGL_HORIZONTAL_RESOLUTION:
360 *value = surface->HorizontalResolution;
361 return EGL_TRUE;
362 case EGL_VERTICAL_RESOLUTION:
363 *value = surface->VerticalResolution;
364 return EGL_TRUE;
365 case EGL_ALPHA_FORMAT:
366 *value = surface->AlphaFormat;
367 return EGL_TRUE;
368 case EGL_COLORSPACE:
369 *value = surface->Colorspace;
370 return EGL_TRUE;
371 #endif /* EGL_VERSION_1_2 */
372 default:
373 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
374 return EGL_FALSE;
375 }
376 }
377
378
379 /**
380 * Example function - drivers should do a proper implementation.
381 */
382 EGLSurface
383 _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
384 NativeWindowType window, const EGLint *attrib_list)
385 {
386 #if 0 /* THIS IS JUST EXAMPLE CODE */
387 _EGLSurface *surf;
388
389 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
390 if (!surf)
391 return EGL_NO_SURFACE;
392
393 if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) {
394 free(surf);
395 return EGL_NO_SURFACE;
396 }
397
398 _eglSaveSurface(surf);
399
400 return surf->Handle;
401 #endif
402 return EGL_NO_SURFACE;
403 }
404
405
406 /**
407 * Example function - drivers should do a proper implementation.
408 */
409 EGLSurface
410 _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
411 NativePixmapType pixmap, const EGLint *attrib_list)
412 {
413 #if 0 /* THIS IS JUST EXAMPLE CODE */
414 _EGLSurface *surf;
415
416 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
417 if (!surf)
418 return EGL_NO_SURFACE;
419
420 if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) {
421 free(surf);
422 return EGL_NO_SURFACE;
423 }
424
425 _eglSaveSurface(surf);
426
427 return surf->Handle;
428 #endif
429 return EGL_NO_SURFACE;
430 }
431
432
433 /**
434 * Example function - drivers should do a proper implementation.
435 */
436 EGLSurface
437 _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
438 const EGLint *attrib_list)
439 {
440 #if 0 /* THIS IS JUST EXAMPLE CODE */
441 _EGLSurface *surf;
442
443 surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface));
444 if (!surf)
445 return EGL_NO_SURFACE;
446
447 if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) {
448 free(surf);
449 return EGL_NO_SURFACE;
450 }
451
452 _eglSaveSurface(surf);
453
454 return surf->Handle;
455 #endif
456 return EGL_NO_SURFACE;
457 }
458
459
460 /**
461 * Default fallback routine - drivers should usually override this.
462 */
463 EGLBoolean
464 _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
465 {
466 _EGLSurface *surf = _eglLookupSurface(surface);
467 if (surf) {
468 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
469 if (surf->IsBound) {
470 surf->DeletePending = EGL_TRUE;
471 }
472 else {
473 free(surf);
474 }
475 return EGL_TRUE;
476 }
477 else {
478 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
479 return EGL_FALSE;
480 }
481 }
482
483
484 /**
485 * Default fallback routine - drivers might override this.
486 */
487 EGLBoolean
488 _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
489 EGLint attribute, EGLint value)
490 {
491 _EGLSurface *surface = _eglLookupSurface(surf);
492
493 if (surface == NULL) {
494 _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib");
495 return EGL_FALSE;
496 }
497
498 switch (attribute) {
499 case EGL_MIPMAP_LEVEL:
500 surface->MipmapLevel = value;
501 break;
502 default:
503 _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib");
504 return EGL_FALSE;
505 }
506 return EGL_TRUE;
507 }
508
509
510 EGLBoolean
511 _eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
512 EGLint buffer)
513 {
514 /* Just do basic error checking and return success/fail.
515 * Drivers must implement the real stuff.
516 */
517 _EGLSurface *surface = _eglLookupSurface(surf);
518
519 if (!surface || surface->Type != EGL_PBUFFER_BIT) {
520 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
521 return EGL_FALSE;
522 }
523
524 if (surface->TextureFormat == EGL_NO_TEXTURE) {
525 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
526 return EGL_FALSE;
527 }
528
529 if (buffer != EGL_BACK_BUFFER) {
530 _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
531 return EGL_FALSE;
532 }
533
534 surface->BoundToTexture = EGL_TRUE;
535
536 return EGL_TRUE;
537 }
538
539
540 EGLBoolean
541 _eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
542 EGLint buffer)
543 {
544 /* Just do basic error checking and return success/fail.
545 * Drivers must implement the real stuff.
546 */
547 _EGLSurface *surface = _eglLookupSurface(surf);
548
549 if (!surface || surface->Type != EGL_PBUFFER_BIT) {
550 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
551 return EGL_FALSE;
552 }
553
554 if (surface->TextureFormat == EGL_NO_TEXTURE) {
555 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
556 return EGL_FALSE;
557 }
558
559 if (buffer != EGL_BACK_BUFFER) {
560 _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
561 return EGL_FALSE;
562 }
563
564 if (!surface->BoundToTexture) {
565 _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
566 return EGL_FALSE;
567 }
568
569 surface->BoundToTexture = EGL_FALSE;
570
571 return EGL_TRUE;
572 }
573
574
575 EGLBoolean
576 _eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval)
577 {
578 _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
579 if (surf == NULL) {
580 _eglError(EGL_BAD_SURFACE, "eglSwapInterval");
581 return EGL_FALSE;
582 }
583 surf->SwapInterval = interval;
584 return EGL_TRUE;
585 }
586
587
588 #ifdef EGL_VERSION_1_2
589
590 /**
591 * Example function - drivers should do a proper implementation.
592 */
593 EGLSurface
594 _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy,
595 EGLenum buftype, EGLClientBuffer buffer,
596 EGLConfig config, const EGLint *attrib_list)
597 {
598 if (buftype != EGL_OPENVG_IMAGE) {
599 _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
600 return EGL_NO_SURFACE;
601 }
602
603 return EGL_NO_SURFACE;
604 }
605
606 #endif /* EGL_VERSION_1_2 */