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