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