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