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