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