egl: Move fallback routines to eglfallbacks.c.
[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 _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
308 EGLint attribute, EGLint *value)
309 {
310 switch (attribute) {
311 case EGL_WIDTH:
312 *value = surface->Width;
313 break;
314 case EGL_HEIGHT:
315 *value = surface->Height;
316 break;
317 case EGL_CONFIG_ID:
318 *value = surface->Config->ConfigID;
319 break;
320 case EGL_LARGEST_PBUFFER:
321 *value = surface->LargestPbuffer;
322 break;
323 case EGL_TEXTURE_FORMAT:
324 /* texture attributes: only for pbuffers, no error otherwise */
325 if (surface->Type == EGL_PBUFFER_BIT)
326 *value = surface->TextureFormat;
327 break;
328 case EGL_TEXTURE_TARGET:
329 if (surface->Type == EGL_PBUFFER_BIT)
330 *value = surface->TextureTarget;
331 break;
332 case EGL_MIPMAP_TEXTURE:
333 if (surface->Type == EGL_PBUFFER_BIT)
334 *value = surface->MipmapTexture;
335 break;
336 case EGL_MIPMAP_LEVEL:
337 if (surface->Type == EGL_PBUFFER_BIT)
338 *value = surface->MipmapLevel;
339 break;
340 case EGL_SWAP_BEHAVIOR:
341 *value = surface->SwapBehavior;
342 break;
343 case EGL_RENDER_BUFFER:
344 *value = surface->RenderBuffer;
345 break;
346 case EGL_PIXEL_ASPECT_RATIO:
347 *value = surface->AspectRatio;
348 break;
349 case EGL_HORIZONTAL_RESOLUTION:
350 *value = surface->HorizontalResolution;
351 break;
352 case EGL_VERTICAL_RESOLUTION:
353 *value = surface->VerticalResolution;
354 break;
355 case EGL_MULTISAMPLE_RESOLVE:
356 *value = surface->MultisampleResolve;
357 break;
358 case EGL_VG_ALPHA_FORMAT:
359 *value = surface->VGAlphaFormat;
360 break;
361 case EGL_VG_COLORSPACE:
362 *value = surface->VGColorspace;
363 break;
364 default:
365 _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
366 return EGL_FALSE;
367 }
368
369 return EGL_TRUE;
370 }
371
372
373 /**
374 * Default fallback routine - drivers might override this.
375 */
376 EGLBoolean
377 _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
378 EGLint attribute, EGLint value)
379 {
380 EGLint confval;
381 EGLint err = EGL_SUCCESS;
382
383 switch (attribute) {
384 case EGL_MIPMAP_LEVEL:
385 confval = surface->Config->RenderableType;
386 if (!(confval & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT))) {
387 err = EGL_BAD_PARAMETER;
388 break;
389 }
390 surface->MipmapLevel = value;
391 break;
392 case EGL_MULTISAMPLE_RESOLVE:
393 switch (value) {
394 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
395 break;
396 case EGL_MULTISAMPLE_RESOLVE_BOX:
397 confval = surface->Config->SurfaceType;
398 if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
399 err = EGL_BAD_MATCH;
400 break;
401 default:
402 err = EGL_BAD_ATTRIBUTE;
403 break;
404 }
405 if (err != EGL_SUCCESS)
406 break;
407 surface->MultisampleResolve = value;
408 break;
409 case EGL_SWAP_BEHAVIOR:
410 switch (value) {
411 case EGL_BUFFER_DESTROYED:
412 break;
413 case EGL_BUFFER_PRESERVED:
414 confval = surface->Config->SurfaceType;
415 if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
416 err = EGL_BAD_MATCH;
417 break;
418 default:
419 err = EGL_BAD_ATTRIBUTE;
420 break;
421 }
422 if (err != EGL_SUCCESS)
423 break;
424 surface->SwapBehavior = value;
425 break;
426 default:
427 err = EGL_BAD_ATTRIBUTE;
428 break;
429 }
430
431 if (err != EGL_SUCCESS)
432 return _eglError(err, "eglSurfaceAttrib");
433 return EGL_TRUE;
434 }
435
436
437 EGLBoolean
438 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
439 EGLint buffer)
440 {
441 EGLint texture_type = EGL_PBUFFER_BIT;
442
443 /* Just do basic error checking and return success/fail.
444 * Drivers must implement the real stuff.
445 */
446
447 if (dpy->Extensions.NOK_texture_from_pixmap)
448 texture_type |= EGL_PIXMAP_BIT;
449
450 if (!(surface->Type & texture_type)) {
451 _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
452 return EGL_FALSE;
453 }
454
455 if (surface->TextureFormat == EGL_NO_TEXTURE) {
456 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
457 return EGL_FALSE;
458 }
459
460 if (surface->TextureTarget == EGL_NO_TEXTURE) {
461 _eglError(EGL_BAD_MATCH, "eglBindTexImage");
462 return EGL_FALSE;
463 }
464
465 if (buffer != EGL_BACK_BUFFER) {
466 _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
467 return EGL_FALSE;
468 }
469
470 surface->BoundToTexture = EGL_TRUE;
471
472 return EGL_TRUE;
473 }
474
475
476 EGLBoolean
477 _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
478 EGLint interval)
479 {
480 _eglClampSwapInterval(surf, interval);
481 return EGL_TRUE;
482 }