1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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
;
64 #ifdef EGL_MESA_screen_surface
66 _eglParseScreenSurfaceAttribList(_EGLSurface
*surf
, const EGLint
*attrib_list
)
68 EGLint i
, err
= EGL_SUCCESS
;
73 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
++) {
74 EGLint attr
= attrib_list
[i
++];
75 EGLint val
= attrib_list
[i
];
80 err
= EGL_BAD_PARAMETER
;
87 err
= EGL_BAD_PARAMETER
;
93 err
= EGL_BAD_ATTRIBUTE
;
97 if (err
!= EGL_SUCCESS
) {
98 _eglLog(_EGL_WARNING
, "bad surface attribute 0x%04x", attr
);
105 #endif /* EGL_MESA_screen_surface */
109 * Parse the list of surface attributes and return the proper error code.
112 _eglParseSurfaceAttribList(_EGLSurface
*surf
, const EGLint
*attrib_list
)
114 _EGLDisplay
*dpy
= surf
->Resource
.Display
;
115 EGLint type
= surf
->Type
;
116 EGLint texture_type
= EGL_PBUFFER_BIT
;
117 EGLint i
, err
= EGL_SUCCESS
;
122 #ifdef EGL_MESA_screen_surface
123 if (type
== EGL_SCREEN_BIT_MESA
)
124 return _eglParseScreenSurfaceAttribList(surf
, attrib_list
);
127 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
128 texture_type
|= EGL_PIXMAP_BIT
;
130 for (i
= 0; attrib_list
[i
] != EGL_NONE
; i
++) {
131 EGLint attr
= attrib_list
[i
++];
132 EGLint val
= attrib_list
[i
];
135 /* common attributes */
136 case EGL_VG_COLORSPACE
:
138 case EGL_VG_COLORSPACE_sRGB
:
139 case EGL_VG_COLORSPACE_LINEAR
:
142 err
= EGL_BAD_ATTRIBUTE
;
145 if (err
!= EGL_SUCCESS
)
147 surf
->VGColorspace
= val
;
149 case EGL_VG_ALPHA_FORMAT
:
151 case EGL_VG_ALPHA_FORMAT_NONPRE
:
152 case EGL_VG_ALPHA_FORMAT_PRE
:
155 err
= EGL_BAD_ATTRIBUTE
;
158 if (err
!= EGL_SUCCESS
)
160 surf
->VGAlphaFormat
= val
;
162 /* window surface attributes */
163 case EGL_RENDER_BUFFER
:
164 if (type
!= EGL_WINDOW_BIT
) {
165 err
= EGL_BAD_ATTRIBUTE
;
168 if (val
!= EGL_BACK_BUFFER
&& val
!= EGL_SINGLE_BUFFER
) {
169 err
= EGL_BAD_ATTRIBUTE
;
172 surf
->RenderBuffer
= val
;
174 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
175 if (!dpy
->Extensions
.NV_post_sub_buffer
||
176 type
!= EGL_WINDOW_BIT
) {
177 err
= EGL_BAD_ATTRIBUTE
;
180 if (val
!= EGL_TRUE
&& val
!= EGL_FALSE
) {
181 err
= EGL_BAD_PARAMETER
;
184 surf
->PostSubBufferSupportedNV
= val
;
186 /* pbuffer surface attributes */
188 if (type
!= EGL_PBUFFER_BIT
) {
189 err
= EGL_BAD_ATTRIBUTE
;
193 err
= EGL_BAD_PARAMETER
;
199 if (type
!= EGL_PBUFFER_BIT
) {
200 err
= EGL_BAD_ATTRIBUTE
;
204 err
= EGL_BAD_PARAMETER
;
209 case EGL_LARGEST_PBUFFER
:
210 if (type
!= EGL_PBUFFER_BIT
) {
211 err
= EGL_BAD_ATTRIBUTE
;
214 surf
->LargestPbuffer
= !!val
;
216 /* for eglBindTexImage */
217 case EGL_TEXTURE_FORMAT
:
218 if (!(type
& texture_type
)) {
219 err
= EGL_BAD_ATTRIBUTE
;
223 case EGL_TEXTURE_RGB
:
224 case EGL_TEXTURE_RGBA
:
228 err
= EGL_BAD_ATTRIBUTE
;
231 if (err
!= EGL_SUCCESS
)
233 surf
->TextureFormat
= val
;
235 case EGL_TEXTURE_TARGET
:
236 if (!(type
& texture_type
)) {
237 err
= EGL_BAD_ATTRIBUTE
;
245 err
= EGL_BAD_ATTRIBUTE
;
248 if (err
!= EGL_SUCCESS
)
250 surf
->TextureTarget
= val
;
252 case EGL_MIPMAP_TEXTURE
:
253 if (!(type
& texture_type
)) {
254 err
= EGL_BAD_ATTRIBUTE
;
257 surf
->MipmapTexture
= !!val
;
259 /* no pixmap surface specific attributes */
261 err
= EGL_BAD_ATTRIBUTE
;
265 if (err
!= EGL_SUCCESS
) {
266 _eglLog(_EGL_WARNING
, "bad surface attribute 0x%04x", attr
);
276 * Do error check on parameters and initialize the given _EGLSurface object.
277 * \return EGL_TRUE if no errors, EGL_FALSE otherwise.
280 _eglInitSurface(_EGLSurface
*surf
, _EGLDisplay
*dpy
, EGLint type
,
281 _EGLConfig
*conf
, const EGLint
*attrib_list
)
284 EGLint renderBuffer
= EGL_BACK_BUFFER
;
285 EGLint swapBehavior
= EGL_BUFFER_PRESERVED
;
290 func
= "eglCreateWindowSurface";
291 swapBehavior
= EGL_BUFFER_DESTROYED
;
294 func
= "eglCreatePixmapSurface";
295 renderBuffer
= EGL_SINGLE_BUFFER
;
297 case EGL_PBUFFER_BIT
:
298 func
= "eglCreatePBufferSurface";
300 #ifdef EGL_MESA_screen_surface
301 case EGL_SCREEN_BIT_MESA
:
302 func
= "eglCreateScreenSurface";
303 renderBuffer
= EGL_SINGLE_BUFFER
; /* XXX correct? */
307 _eglLog(_EGL_WARNING
, "Bad type in _eglInitSurface");
311 if ((conf
->SurfaceType
& type
) == 0) {
312 /* The config can't be used to create a surface of this type */
313 _eglError(EGL_BAD_CONFIG
, func
);
317 _eglInitResource(&surf
->Resource
, sizeof(*surf
), dpy
);
323 surf
->TextureFormat
= EGL_NO_TEXTURE
;
324 surf
->TextureTarget
= EGL_NO_TEXTURE
;
325 surf
->MipmapTexture
= EGL_FALSE
;
326 surf
->LargestPbuffer
= EGL_FALSE
;
327 surf
->RenderBuffer
= renderBuffer
;
328 surf
->VGAlphaFormat
= EGL_VG_ALPHA_FORMAT_NONPRE
;
329 surf
->VGColorspace
= EGL_VG_COLORSPACE_sRGB
;
331 surf
->MipmapLevel
= 0;
332 surf
->MultisampleResolve
= EGL_MULTISAMPLE_RESOLVE_DEFAULT
;
333 surf
->SwapBehavior
= swapBehavior
;
335 surf
->HorizontalResolution
= EGL_UNKNOWN
;
336 surf
->VerticalResolution
= EGL_UNKNOWN
;
337 surf
->AspectRatio
= EGL_UNKNOWN
;
339 surf
->PostSubBufferSupportedNV
= EGL_FALSE
;
341 /* the default swap interval is 1 */
342 _eglClampSwapInterval(surf
, 1);
344 err
= _eglParseSurfaceAttribList(surf
, attrib_list
);
345 if (err
!= EGL_SUCCESS
)
346 return _eglError(err
, func
);
353 _eglQuerySurface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
354 EGLint attribute
, EGLint
*value
)
358 *value
= surface
->Width
;
361 *value
= surface
->Height
;
364 *value
= surface
->Config
->ConfigID
;
366 case EGL_LARGEST_PBUFFER
:
367 *value
= surface
->LargestPbuffer
;
369 case EGL_TEXTURE_FORMAT
:
370 /* texture attributes: only for pbuffers, no error otherwise */
371 if (surface
->Type
== EGL_PBUFFER_BIT
)
372 *value
= surface
->TextureFormat
;
374 case EGL_TEXTURE_TARGET
:
375 if (surface
->Type
== EGL_PBUFFER_BIT
)
376 *value
= surface
->TextureTarget
;
378 case EGL_MIPMAP_TEXTURE
:
379 if (surface
->Type
== EGL_PBUFFER_BIT
)
380 *value
= surface
->MipmapTexture
;
382 case EGL_MIPMAP_LEVEL
:
383 if (surface
->Type
== EGL_PBUFFER_BIT
)
384 *value
= surface
->MipmapLevel
;
386 case EGL_SWAP_BEHAVIOR
:
387 *value
= surface
->SwapBehavior
;
389 case EGL_RENDER_BUFFER
:
390 *value
= surface
->RenderBuffer
;
392 case EGL_PIXEL_ASPECT_RATIO
:
393 *value
= surface
->AspectRatio
;
395 case EGL_HORIZONTAL_RESOLUTION
:
396 *value
= surface
->HorizontalResolution
;
398 case EGL_VERTICAL_RESOLUTION
:
399 *value
= surface
->VerticalResolution
;
401 case EGL_MULTISAMPLE_RESOLVE
:
402 *value
= surface
->MultisampleResolve
;
404 case EGL_VG_ALPHA_FORMAT
:
405 *value
= surface
->VGAlphaFormat
;
407 case EGL_VG_COLORSPACE
:
408 *value
= surface
->VGColorspace
;
410 case EGL_POST_SUB_BUFFER_SUPPORTED_NV
:
411 *value
= surface
->PostSubBufferSupportedNV
;
413 case EGL_BUFFER_AGE_EXT
:
414 if (!dpy
->Extensions
.EXT_buffer_age
) {
415 _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
418 *value
= drv
->API
.QueryBufferAge(drv
, dpy
, surface
);
421 _eglError(EGL_BAD_ATTRIBUTE
, "eglQuerySurface");
430 * Default fallback routine - drivers might override this.
433 _eglSurfaceAttrib(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
434 EGLint attribute
, EGLint value
)
437 EGLint err
= EGL_SUCCESS
;
438 EGLint all_es_bits
= EGL_OPENGL_ES_BIT
|
440 EGL_OPENGL_ES3_BIT_KHR
;
443 case EGL_MIPMAP_LEVEL
:
444 confval
= surface
->Config
->RenderableType
;
445 if (!(confval
& all_es_bits
)) {
446 err
= EGL_BAD_PARAMETER
;
449 surface
->MipmapLevel
= value
;
451 case EGL_MULTISAMPLE_RESOLVE
:
453 case EGL_MULTISAMPLE_RESOLVE_DEFAULT
:
455 case EGL_MULTISAMPLE_RESOLVE_BOX
:
456 confval
= surface
->Config
->SurfaceType
;
457 if (!(confval
& EGL_MULTISAMPLE_RESOLVE_BOX_BIT
))
461 err
= EGL_BAD_ATTRIBUTE
;
464 if (err
!= EGL_SUCCESS
)
466 surface
->MultisampleResolve
= value
;
468 case EGL_SWAP_BEHAVIOR
:
470 case EGL_BUFFER_DESTROYED
:
472 case EGL_BUFFER_PRESERVED
:
473 confval
= surface
->Config
->SurfaceType
;
474 if (!(confval
& EGL_SWAP_BEHAVIOR_PRESERVED_BIT
))
478 err
= EGL_BAD_ATTRIBUTE
;
481 if (err
!= EGL_SUCCESS
)
483 surface
->SwapBehavior
= value
;
486 err
= EGL_BAD_ATTRIBUTE
;
490 if (err
!= EGL_SUCCESS
)
491 return _eglError(err
, "eglSurfaceAttrib");
497 _eglBindTexImage(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
,
500 EGLint texture_type
= EGL_PBUFFER_BIT
;
502 /* Just do basic error checking and return success/fail.
503 * Drivers must implement the real stuff.
506 if (dpy
->Extensions
.NOK_texture_from_pixmap
)
507 texture_type
|= EGL_PIXMAP_BIT
;
509 if (!(surface
->Type
& texture_type
)) {
510 _eglError(EGL_BAD_SURFACE
, "eglBindTexImage");
514 if (surface
->TextureFormat
== EGL_NO_TEXTURE
) {
515 _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
519 if (surface
->TextureTarget
== EGL_NO_TEXTURE
) {
520 _eglError(EGL_BAD_MATCH
, "eglBindTexImage");
524 if (buffer
!= EGL_BACK_BUFFER
) {
525 _eglError(EGL_BAD_PARAMETER
, "eglBindTexImage");
529 surface
->BoundToTexture
= EGL_TRUE
;
536 _eglSwapInterval(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surf
,
539 _eglClampSwapInterval(surf
, interval
);