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 * Parse the list of surface attributes and return the proper error code.
52 _eglParseSurfaceAttribList(_EGLSurface
*surf
, const EGLint
*attrib_list
)
54 _EGLDisplay
*dpy
= surf
->Resource
.Display
;
55 EGLint type
= surf
->Type
;
56 EGLint texture_type
= EGL_PBUFFER_BIT
;
57 EGLint i
, err
= EGL_SUCCESS
;
58 EGLint attr
= EGL_NONE
;
59 EGLint val
= EGL_NONE
;
64 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
65 texture_type
|= EGL_PIXMAP_BIT
;
67 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
++) {
68 attr
= attrib_list
[i
++];
72 /* common attributes */
73 case EGL_GL_COLORSPACE_KHR
:
74 if (!dpy
->Extensions
.KHR_gl_colorspace
) {
75 err
= EGL_BAD_ATTRIBUTE
;
79 case EGL_GL_COLORSPACE_SRGB_KHR
:
80 case EGL_GL_COLORSPACE_LINEAR_KHR
:
83 err
= EGL_BAD_ATTRIBUTE
;
85 if (err
!= EGL_SUCCESS
)
87 surf
->GLColorspace
= val
;
89 case EGL_VG_COLORSPACE
:
91 case EGL_VG_COLORSPACE_sRGB
:
92 case EGL_VG_COLORSPACE_LINEAR
:
95 err
= EGL_BAD_ATTRIBUTE
;
98 if (err
!= EGL_SUCCESS
)
100 surf
->VGColorspace
= val
;
102 case EGL_VG_ALPHA_FORMAT
:
104 case EGL_VG_ALPHA_FORMAT_NONPRE
:
105 case EGL_VG_ALPHA_FORMAT_PRE
:
108 err
= EGL_BAD_ATTRIBUTE
;
111 if (err
!= EGL_SUCCESS
)
113 surf
->VGAlphaFormat
= val
;
115 /* window surface attributes */
116 case EGL_RENDER_BUFFER
:
117 if (type
!= EGL_WINDOW_BIT
) {
118 err
= EGL_BAD_ATTRIBUTE
;
121 if (val
!= EGL_BACK_BUFFER
&& val
!= EGL_SINGLE_BUFFER
) {
122 err
= EGL_BAD_ATTRIBUTE
;
125 surf
->RenderBuffer
= val
;
127 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
128 if (!dpy
->Extensions
.NV_post_sub_buffer
||
129 type
!= EGL_WINDOW_BIT
) {
130 err
= EGL_BAD_ATTRIBUTE
;
133 if (val
!= EGL_TRUE
&& val
!= EGL_FALSE
) {
134 err
= EGL_BAD_PARAMETER
;
137 surf
->PostSubBufferSupportedNV
= val
;
139 /* pbuffer surface attributes */
141 if (type
!= EGL_PBUFFER_BIT
) {
142 err
= EGL_BAD_ATTRIBUTE
;
146 err
= EGL_BAD_PARAMETER
;
152 if (type
!= EGL_PBUFFER_BIT
) {
153 err
= EGL_BAD_ATTRIBUTE
;
157 err
= EGL_BAD_PARAMETER
;
162 case EGL_LARGEST_PBUFFER
:
163 if (type
!= EGL_PBUFFER_BIT
) {
164 err
= EGL_BAD_ATTRIBUTE
;
167 surf
->LargestPbuffer
= !!val
;
169 /* for eglBindTexImage */
170 case EGL_TEXTURE_FORMAT
:
171 if (!(type
& texture_type
)) {
172 err
= EGL_BAD_ATTRIBUTE
;
177 case EGL_TEXTURE_RGB
:
178 case EGL_TEXTURE_RGBA
:
182 err
= EGL_BAD_ATTRIBUTE
;
185 if (err
!= EGL_SUCCESS
)
187 surf
->TextureFormat
= val
;
189 case EGL_TEXTURE_TARGET
:
190 if (!(type
& texture_type
)) {
191 err
= EGL_BAD_ATTRIBUTE
;
200 err
= EGL_BAD_ATTRIBUTE
;
203 if (err
!= EGL_SUCCESS
)
205 surf
->TextureTarget
= val
;
207 case EGL_MIPMAP_TEXTURE
:
208 if (!(type
& texture_type
)) {
209 err
= EGL_BAD_ATTRIBUTE
;
212 surf
->MipmapTexture
= !!val
;
214 /* no pixmap surface specific attributes */
216 err
= EGL_BAD_ATTRIBUTE
;
220 if (err
!= EGL_SUCCESS
)
224 if (err
== EGL_SUCCESS
&& type
== EGL_PBUFFER_BIT
) {
225 if ((surf
->TextureTarget
== EGL_NO_TEXTURE
&& surf
->TextureFormat
!= EGL_NO_TEXTURE
) ||
226 (surf
->TextureFormat
== EGL_NO_TEXTURE
&& surf
->TextureTarget
!= EGL_NO_TEXTURE
)) {
227 attr
= surf
->TextureTarget
== EGL_NO_TEXTURE
? EGL_TEXTURE_TARGET
: EGL_TEXTURE_FORMAT
;
232 if (err
!= EGL_SUCCESS
)
233 _eglLog(_EGL_WARNING
, "bad surface attribute 0x%04x", attr
);
240 * Do error check on parameters and initialize the given _EGLSurface object.
241 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
244 _eglInitSurface(_EGLSurface
*surf
, _EGLDisplay
*dpy
, EGLint type
,
245 _EGLConfig
*conf
, const EGLint
*attrib_list
)
248 EGLint renderBuffer
= EGL_BACK_BUFFER
;
249 EGLint swapBehavior
= EGL_BUFFER_DESTROYED
;
252 /* Swap behavior can be preserved only if config supports this. */
253 if (conf
->SurfaceType
& EGL_SWAP_BEHAVIOR_PRESERVED_BIT
)
254 swapBehavior
= EGL_BUFFER_PRESERVED
;
258 func
= "eglCreateWindowSurface";
259 swapBehavior
= EGL_BUFFER_DESTROYED
;
262 func
= "eglCreatePixmapSurface";
263 renderBuffer
= EGL_SINGLE_BUFFER
;
265 case EGL_PBUFFER_BIT
:
266 func
= "eglCreatePBufferSurface";
269 _eglLog(_EGL_WARNING
, "Bad type in _eglInitSurface");
273 if ((conf
->SurfaceType
& type
) == 0)
274 /* The config can't be used to create a surface of this type */
275 return _eglError(EGL_BAD_MATCH
, func
);
277 _eglInitResource(&surf
->Resource
, sizeof(*surf
), dpy
);
280 surf
->Lost
= EGL_FALSE
;
284 surf
->TextureFormat
= EGL_NO_TEXTURE
;
285 surf
->TextureTarget
= EGL_NO_TEXTURE
;
286 surf
->MipmapTexture
= EGL_FALSE
;
287 surf
->LargestPbuffer
= EGL_FALSE
;
288 surf
->RenderBuffer
= renderBuffer
;
289 surf
->VGAlphaFormat
= EGL_VG_ALPHA_FORMAT_NONPRE
;
290 surf
->VGColorspace
= EGL_VG_COLORSPACE_sRGB
;
291 surf
->GLColorspace
= EGL_GL_COLORSPACE_LINEAR_KHR
;
293 surf
->MipmapLevel
= 0;
294 surf
->MultisampleResolve
= EGL_MULTISAMPLE_RESOLVE_DEFAULT
;
295 surf
->SwapBehavior
= swapBehavior
;
297 surf
->HorizontalResolution
= EGL_UNKNOWN
;
298 surf
->VerticalResolution
= EGL_UNKNOWN
;
299 surf
->AspectRatio
= EGL_UNKNOWN
;
301 surf
->PostSubBufferSupportedNV
= EGL_FALSE
;
302 surf
->SetDamageRegionCalled
= EGL_FALSE
;
303 surf
->BufferAgeRead
= EGL_FALSE
;
305 /* the default swap interval is 1 */
306 surf
->SwapInterval
= 1;
308 err
= _eglParseSurfaceAttribList(surf
, attrib_list
);
309 if (err
!= EGL_SUCCESS
)
310 return _eglError(err
, func
);
312 /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
313 if (surf
->LargestPbuffer
) {
314 surf
->Width
= MIN2(surf
->Width
, _EGL_MAX_PBUFFER_WIDTH
);
315 surf
->Height
= MIN2(surf
->Height
, _EGL_MAX_PBUFFER_HEIGHT
);
323 _eglQuerySurface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
324 EGLint attribute
, EGLint
*value
)
328 *value
= surface
->Width
;
331 *value
= surface
->Height
;
334 *value
= surface
->Config
->ConfigID
;
336 case EGL_LARGEST_PBUFFER
:
337 if (surface
->Type
== EGL_PBUFFER_BIT
)
338 *value
= surface
->LargestPbuffer
;
340 case EGL_TEXTURE_FORMAT
:
341 /* texture attributes: only for pbuffers, no error otherwise */
342 if (surface
->Type
== EGL_PBUFFER_BIT
)
343 *value
= surface
->TextureFormat
;
345 case EGL_TEXTURE_TARGET
:
346 if (surface
->Type
== EGL_PBUFFER_BIT
)
347 *value
= surface
->TextureTarget
;
349 case EGL_MIPMAP_TEXTURE
:
350 if (surface
->Type
== EGL_PBUFFER_BIT
)
351 *value
= surface
->MipmapTexture
;
353 case EGL_MIPMAP_LEVEL
:
354 if (surface
->Type
== EGL_PBUFFER_BIT
)
355 *value
= surface
->MipmapLevel
;
357 case EGL_SWAP_BEHAVIOR
:
358 *value
= surface
->SwapBehavior
;
360 case EGL_RENDER_BUFFER
:
361 *value
= surface
->RenderBuffer
;
363 case EGL_PIXEL_ASPECT_RATIO
:
364 *value
= surface
->AspectRatio
;
366 case EGL_HORIZONTAL_RESOLUTION
:
367 *value
= surface
->HorizontalResolution
;
369 case EGL_VERTICAL_RESOLUTION
:
370 *value
= surface
->VerticalResolution
;
372 case EGL_MULTISAMPLE_RESOLVE
:
373 *value
= surface
->MultisampleResolve
;
375 case EGL_VG_ALPHA_FORMAT
:
376 *value
= surface
->VGAlphaFormat
;
378 case EGL_VG_COLORSPACE
:
379 *value
= surface
->VGColorspace
;
381 case EGL_GL_COLORSPACE_KHR
:
382 if (!dpy
->Extensions
.KHR_gl_colorspace
)
383 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
385 *value
= surface
->GLColorspace
;
387 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
388 *value
= surface
->PostSubBufferSupportedNV
;
390 case EGL_BUFFER_AGE_EXT
:
391 if (!dpy
->Extensions
.EXT_buffer_age
)
392 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
394 _EGLContext
*ctx
= _eglGetCurrentContext();
395 EGLint result
= drv
->API
.QueryBufferAge(drv
, dpy
, surface
);
399 if (_eglGetContextHandle(ctx
) == EGL_NO_CONTEXT
||
400 ctx
->DrawSurface
!= surface
)
401 return _eglError(EGL_BAD_SURFACE
, "eglQuerySurface");
404 surface
->BufferAgeRead
= EGL_TRUE
;
407 return _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
415 * Default fallback routine - drivers might override this.
418 _eglSurfaceAttrib(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
419 EGLint attribute
, EGLint value
)
422 EGLint err
= EGL_SUCCESS
;
423 EGLint all_es_bits
= EGL_OPENGL_ES_BIT
|
425 EGL_OPENGL_ES3_BIT_KHR
;
428 case EGL_MIPMAP_LEVEL
:
429 confval
= surface
->Config
->RenderableType
;
430 if (!(confval
& all_es_bits
)) {
431 err
= EGL_BAD_PARAMETER
;
434 surface
->MipmapLevel
= value
;
436 case EGL_MULTISAMPLE_RESOLVE
:
438 case EGL_MULTISAMPLE_RESOLVE_DEFAULT
:
440 case EGL_MULTISAMPLE_RESOLVE_BOX
:
441 confval
= surface
->Config
->SurfaceType
;
442 if (!(confval
& EGL_MULTISAMPLE_RESOLVE_BOX_BIT
))
446 err
= EGL_BAD_ATTRIBUTE
;
449 if (err
!= EGL_SUCCESS
)
451 surface
->MultisampleResolve
= value
;
453 case EGL_SWAP_BEHAVIOR
:
455 case EGL_BUFFER_DESTROYED
:
457 case EGL_BUFFER_PRESERVED
:
458 confval
= surface
->Config
->SurfaceType
;
459 if (!(confval
& EGL_SWAP_BEHAVIOR_PRESERVED_BIT
))
463 err
= EGL_BAD_ATTRIBUTE
;
466 if (err
!= EGL_SUCCESS
)
468 surface
->SwapBehavior
= value
;
471 err
= EGL_BAD_ATTRIBUTE
;
475 if (err
!= EGL_SUCCESS
)
476 return _eglError(err
, "eglSurfaceAttrib");
482 _eglBindTexImage(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
485 EGLint texture_type
= EGL_PBUFFER_BIT
;
487 /* Just do basic error checking and return success/fail.
488 * Drivers must implement the real stuff.
491 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
492 texture_type
|= EGL_PIXMAP_BIT
;
494 if (!(surface
->Type
& texture_type
))
495 return _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
497 if (surface
->TextureFormat
== EGL_NO_TEXTURE
)
498 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
500 if (surface
->TextureTarget
== EGL_NO_TEXTURE
)
501 return _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
503 if (buffer
!= EGL_BACK_BUFFER
)
504 return _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
506 surface
->BoundToTexture
= EGL_TRUE
;
512 _eglReleaseTexImage(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
515 /* Just do basic error checking and return success/fail.
516 * Drivers must implement the real stuff.
519 EGLint texture_type
= EGL_PBUFFER_BIT
;
521 if (surf
== EGL_NO_SURFACE
)
522 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
524 if (!surf
->BoundToTexture
)
526 /* Not an error, simply nothing to do */
530 if (surf
->TextureFormat
== EGL_NO_TEXTURE
)
531 return _eglError(EGL_BAD_MATCH
, "eglReleaseTexImage");
533 if (buffer
!= EGL_BACK_BUFFER
)
534 return _eglError(EGL_BAD_PARAMETER
, "eglReleaseTexImage");
536 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
537 texture_type
|= EGL_PIXMAP_BIT
;
539 if (!(surf
->Type
& texture_type
))
540 return _eglError(EGL_BAD_SURFACE
, "eglReleaseTexImage");
542 surf
->BoundToTexture
= EGL_FALSE
;
549 _eglSwapInterval(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,