OSDN Git Service

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