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