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