eglsurface.c revision ecb3b3102a3022e31cf9d75ae099eddbe298517f
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
18static 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 */
38EGLBoolean
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
230EGLBoolean
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
238EGLBoolean
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
248EGLBoolean
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 */
395EGLBoolean
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 */
407EGLBoolean
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
423EGLBoolean
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
452EGLBoolean
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
486EGLBoolean
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 */
514