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