1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010 LunarG, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Surface-related functions.
39 #include "egldisplay.h"
40 #include "egldriver.h"
41 #include "eglcontext.h"
42 #include "eglconfig.h"
43 #include "eglcurrent.h"
45 #include "eglsurface.h"
49 _eglClampSwapInterval(_EGLSurface
*surf
, EGLint interval
)
51 EGLint bound
= surf
->Config
->MaxSwapInterval
;
52 if (interval
>= bound
) {
56 bound
= surf
->Config
->MinSwapInterval
;
60 surf
->SwapInterval
= interval
;
65 * Parse the list of surface attributes and return the proper error code.
68 _eglParseSurfaceAttribList(_EGLSurface
*surf
, const EGLint
*attrib_list
)
70 _EGLDisplay
*dpy
= surf
->Resource
.Display
;
71 EGLint type
= surf
->Type
;
72 EGLint texture_type
= EGL_PBUFFER_BIT
;
73 EGLint i
, err
= EGL_SUCCESS
;
74 EGLint attr
= EGL_NONE
;
75 EGLint val
= EGL_NONE
;
80 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
81 texture_type
|= EGL_PIXMAP_BIT
;
83 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
++) {
84 attr
= attrib_list
[i
++];
88 /* common attributes */
89 case EGL_GL_COLORSPACE_KHR
:
90 if (!dpy
->Extensions
.KHR_gl_colorspace
) {
91 err
= EGL_BAD_ATTRIBUTE
;
95 case EGL_GL_COLORSPACE_SRGB_KHR
:
96 case EGL_GL_COLORSPACE_LINEAR_KHR
:
99 err
= EGL_BAD_ATTRIBUTE
;
101 if (err
!= EGL_SUCCESS
)
103 surf
->GLColorspace
= val
;
105 case EGL_VG_COLORSPACE
:
107 case EGL_VG_COLORSPACE_sRGB
:
108 case EGL_VG_COLORSPACE_LINEAR
:
111 err
= EGL_BAD_ATTRIBUTE
;
114 if (err
!= EGL_SUCCESS
)
116 surf
->VGColorspace
= val
;
118 case EGL_VG_ALPHA_FORMAT
:
120 case EGL_VG_ALPHA_FORMAT_NONPRE
:
121 case EGL_VG_ALPHA_FORMAT_PRE
:
124 err
= EGL_BAD_ATTRIBUTE
;
127 if (err
!= EGL_SUCCESS
)
129 surf
->VGAlphaFormat
= val
;
131 /* window surface attributes */
132 case EGL_RENDER_BUFFER
:
133 if (type
!= EGL_WINDOW_BIT
) {
134 err
= EGL_BAD_ATTRIBUTE
;
137 if (val
!= EGL_BACK_BUFFER
&& val
!= EGL_SINGLE_BUFFER
) {
138 err
= EGL_BAD_ATTRIBUTE
;
141 surf
->RenderBuffer
= val
;
143 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
144 if (!dpy
->Extensions
.NV_post_sub_buffer
||
145 type
!= EGL_WINDOW_BIT
) {
146 err
= EGL_BAD_ATTRIBUTE
;
149 if (val
!= EGL_TRUE
&& val
!= EGL_FALSE
) {
150 err
= EGL_BAD_PARAMETER
;
153 surf
->PostSubBufferSupportedNV
= val
;
155 /* pbuffer surface attributes */
157 if (type
!= EGL_PBUFFER_BIT
) {
158 err
= EGL_BAD_ATTRIBUTE
;
162 err
= EGL_BAD_PARAMETER
;
168 if (type
!= EGL_PBUFFER_BIT
) {
169 err
= EGL_BAD_ATTRIBUTE
;
173 err
= EGL_BAD_PARAMETER
;
178 case EGL_LARGEST_PBUFFER
:
179 if (type
!= EGL_PBUFFER_BIT
) {
180 err
= EGL_BAD_ATTRIBUTE
;
183 surf
->LargestPbuffer
= !!val
;
185 /* for eglBindTexImage */
186 case EGL_TEXTURE_FORMAT
:
187 if (!(type
& texture_type
)) {
188 err
= EGL_BAD_ATTRIBUTE
;
193 case EGL_TEXTURE_RGB
:
194 case EGL_TEXTURE_RGBA
:
198 err
= EGL_BAD_ATTRIBUTE
;
201 if (err
!= EGL_SUCCESS
)
203 surf
->TextureFormat
= val
;
205 case EGL_TEXTURE_TARGET
:
206 if (!(type
& texture_type
)) {
207 err
= EGL_BAD_ATTRIBUTE
;
216 err
= EGL_BAD_ATTRIBUTE
;
219 if (err
!= EGL_SUCCESS
)
221 surf
->TextureTarget
= val
;
223 case EGL_MIPMAP_TEXTURE
:
224 if (!(type
& texture_type
)) {
225 err
= EGL_BAD_ATTRIBUTE
;
228 surf
->MipmapTexture
= !!val
;
230 /* no pixmap surface specific attributes */
232 err
= EGL_BAD_ATTRIBUTE
;
236 if (err
!= EGL_SUCCESS
)
240 if (err
== EGL_SUCCESS
&& type
== EGL_PBUFFER_BIT
) {
241 if ((surf
->TextureTarget
== EGL_NO_TEXTURE
&& surf
->TextureFormat
!= EGL_NO_TEXTURE
) ||
242 (surf
->TextureFormat
== EGL_NO_TEXTURE
&& surf
->TextureTarget
!= EGL_NO_TEXTURE
)) {
243 attr
= surf
->TextureTarget
== EGL_NO_TEXTURE
? EGL_TEXTURE_TARGET
: EGL_TEXTURE_FORMAT
;
248 if (err
!= EGL_SUCCESS
)
249 _eglLog(_EGL_WARNING
, "bad surface attribute 0x%04x", attr
);
256 * Do error check on parameters and initialize the given _EGLSurface object.
257 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
260 _eglInitSurface(_EGLSurface
*surf
, _EGLDisplay
*dpy
, EGLint type
,
261 _EGLConfig
*conf
, const EGLint
*attrib_list
)
264 EGLint renderBuffer
= EGL_BACK_BUFFER
;
265 EGLint swapBehavior
= EGL_BUFFER_DESTROYED
;
268 /* Swap behavior can be preserved only if config supports this. */
269 if (conf
->SurfaceType
& EGL_SWAP_BEHAVIOR_PRESERVED_BIT
)
270 swapBehavior
= EGL_BUFFER_PRESERVED
;
274 func
= "eglCreateWindowSurface";
275 swapBehavior
= EGL_BUFFER_DESTROYED
;
278 func
= "eglCreatePixmapSurface";
279 renderBuffer
= EGL_SINGLE_BUFFER
;
281 case EGL_PBUFFER_BIT
:
282 func
= "eglCreatePBufferSurface";
285 _eglLog(_EGL_WARNING
, "Bad type in _eglInitSurface");
289 if ((conf
->SurfaceType
& type
) == 0) {
290 /* The config can't be used to create a surface of this type */
291 _eglError(EGL_BAD_MATCH
, func
);
295 _eglInitResource(&surf
->Resource
, sizeof(*surf
), dpy
);
298 surf
->Lost
= EGL_FALSE
;
302 surf
->TextureFormat
= EGL_NO_TEXTURE
;
303 surf
->TextureTarget
= EGL_NO_TEXTURE
;
304 surf
->MipmapTexture
= EGL_FALSE
;
305 surf
->LargestPbuffer
= EGL_FALSE
;
306 surf
->RenderBuffer
= renderBuffer
;
307 surf
->VGAlphaFormat
= EGL_VG_ALPHA_FORMAT_NONPRE
;
308 surf
->VGColorspace
= EGL_VG_COLORSPACE_sRGB
;
309 surf
->GLColorspace
= EGL_GL_COLORSPACE_LINEAR_KHR
;
311 surf
->MipmapLevel
= 0;
312 surf
->MultisampleResolve
= EGL_MULTISAMPLE_RESOLVE_DEFAULT
;
313 surf
->SwapBehavior
= swapBehavior
;
315 surf
->HorizontalResolution
= EGL_UNKNOWN
;
316 surf
->VerticalResolution
= EGL_UNKNOWN
;
317 surf
->AspectRatio
= EGL_UNKNOWN
;
319 surf
->PostSubBufferSupportedNV
= EGL_FALSE
;
321 /* the default swap interval is 1 */
322 _eglClampSwapInterval(surf
, 1);
324 err
= _eglParseSurfaceAttribList(surf
, attrib_list
);
325 if (err
!= EGL_SUCCESS
)
326 return _eglError(err
, func
);
328 /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
329 if (surf
->LargestPbuffer
) {
330 surf
->Width
= MIN2(surf
->Width
, _EGL_MAX_PBUFFER_WIDTH
);
331 surf
->Height
= MIN2(surf
->Height
, _EGL_MAX_PBUFFER_HEIGHT
);
339 _eglQuerySurface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
340 EGLint attribute
, EGLint
*value
)
344 *value
= surface
->Width
;
347 *value
= surface
->Height
;
350 *value
= surface
->Config
->ConfigID
;
352 case EGL_LARGEST_PBUFFER
:
353 if (surface
->Type
== EGL_PBUFFER_BIT
)
354 *value
= surface
->LargestPbuffer
;
356 case EGL_TEXTURE_FORMAT
:
357 /* texture attributes: only for pbuffers, no error otherwise */
358 if (surface
->Type
== EGL_PBUFFER_BIT
)
359 *value
= surface
->TextureFormat
;
361 case EGL_TEXTURE_TARGET
:
362 if (surface
->Type
== EGL_PBUFFER_BIT
)
363 *value
= surface
->TextureTarget
;
365 case EGL_MIPMAP_TEXTURE
:
366 if (surface
->Type
== EGL_PBUFFER_BIT
)
367 *value
= surface
->MipmapTexture
;
369 case EGL_MIPMAP_LEVEL
:
370 if (surface
->Type
== EGL_PBUFFER_BIT
)
371 *value
= surface
->MipmapLevel
;
373 case EGL_SWAP_BEHAVIOR
:
374 *value
= surface
->SwapBehavior
;
376 case EGL_RENDER_BUFFER
:
377 *value
= surface
->RenderBuffer
;
379 case EGL_PIXEL_ASPECT_RATIO
:
380 *value
= surface
->AspectRatio
;
382 case EGL_HORIZONTAL_RESOLUTION
:
383 *value
= surface
->HorizontalResolution
;
385 case EGL_VERTICAL_RESOLUTION
:
386 *value
= surface
->VerticalResolution
;
388 case EGL_MULTISAMPLE_RESOLVE
:
389 *value
= surface
->MultisampleResolve
;
391 case EGL_VG_ALPHA_FORMAT
:
392 *value
= surface
->VGAlphaFormat
;
394 case EGL_VG_COLORSPACE
:
395 *value
= surface
->VGColorspace
;
397 case EGL_GL_COLORSPACE_KHR
:
398 if (!dpy
->Extensions
.KHR_gl_colorspace
) {
399 _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
402 *value
= surface
->GLColorspace
;
404 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
405 *value
= surface
->PostSubBufferSupportedNV
;
407 case EGL_BUFFER_AGE_EXT
:
408 if (!dpy
->Extensions
.EXT_buffer_age
) {
409 _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
412 EGLint result
= drv
->API
.QueryBufferAge(drv
, dpy
, surface
);
419 _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
428 * Default fallback routine - drivers might override this.
431 _eglSurfaceAttrib(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
432 EGLint attribute
, EGLint value
)
435 EGLint err
= EGL_SUCCESS
;
436 EGLint all_es_bits
= EGL_OPENGL_ES_BIT
|
438 EGL_OPENGL_ES3_BIT_KHR
;
441 case EGL_MIPMAP_LEVEL
:
442 confval
= surface
->Config
->RenderableType
;
443 if (!(confval
& all_es_bits
)) {
444 err
= EGL_BAD_PARAMETER
;
447 surface
->MipmapLevel
= value
;
449 case EGL_MULTISAMPLE_RESOLVE
:
451 case EGL_MULTISAMPLE_RESOLVE_DEFAULT
:
453 case EGL_MULTISAMPLE_RESOLVE_BOX
:
454 confval
= surface
->Config
->SurfaceType
;
455 if (!(confval
& EGL_MULTISAMPLE_RESOLVE_BOX_BIT
))
459 err
= EGL_BAD_ATTRIBUTE
;
462 if (err
!= EGL_SUCCESS
)
464 surface
->MultisampleResolve
= value
;
466 case EGL_SWAP_BEHAVIOR
:
468 case EGL_BUFFER_DESTROYED
:
470 case EGL_BUFFER_PRESERVED
:
471 confval
= surface
->Config
->SurfaceType
;
472 if (!(confval
& EGL_SWAP_BEHAVIOR_PRESERVED_BIT
))
476 err
= EGL_BAD_ATTRIBUTE
;
479 if (err
!= EGL_SUCCESS
)
481 surface
->SwapBehavior
= value
;
484 err
= EGL_BAD_ATTRIBUTE
;
488 if (err
!= EGL_SUCCESS
)
489 return _eglError(err
, "eglSurfaceAttrib");
495 _eglBindTexImage(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
498 EGLint texture_type
= EGL_PBUFFER_BIT
;
500 /* Just do basic error checking and return success/fail.
501 * Drivers must implement the real stuff.
504 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
505 texture_type
|= EGL_PIXMAP_BIT
;
507 if (!(surface
->Type
& texture_type
)) {
508 _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
512 if (surface
->TextureFormat
== EGL_NO_TEXTURE
) {
513 _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
517 if (surface
->TextureTarget
== EGL_NO_TEXTURE
) {
518 _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
522 if (buffer
!= EGL_BACK_BUFFER
) {
523 _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
527 surface
->BoundToTexture
= EGL_TRUE
;
533 _eglReleaseTexImage(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
536 /* Just do basic error checking and return success/fail.
537 * Drivers must implement the real stuff.
540 EGLint texture_type
= EGL_PBUFFER_BIT
;
542 if (surf
== EGL_NO_SURFACE
)
544 _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
548 if (!surf
->BoundToTexture
)
550 /* Not an error, simply nothing to do */
554 if (surf
->TextureFormat
== EGL_NO_TEXTURE
)
556 _eglError(EGL_BAD_MATCH
, "eglReleaseTexImage");
560 if (buffer
!= EGL_BACK_BUFFER
)
562 _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
566 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
567 texture_type
|= EGL_PIXMAP_BIT
;
569 if (!(surf
->Type
& texture_type
))
571 _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
575 surf
->BoundToTexture
= EGL_FALSE
;
582 _eglSwapInterval(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
585 _eglClampSwapInterval(surf
, interval
);