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