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