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