+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright 2010 LunarG, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
/**
* Surface-related functions.
*/
#include <stdlib.h>
#include <string.h>
#include "egldisplay.h"
+#include "egldriver.h"
#include "eglcontext.h"
#include "eglconfig.h"
#include "eglcurrent.h"
#include "eglsurface.h"
-static void
-_eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
-{
- EGLint bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MAX_SWAP_INTERVAL);
- if (interval >= bound) {
- interval = bound;
- }
- else {
- bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MIN_SWAP_INTERVAL);
- if (interval < bound)
- interval = bound;
- }
- surf->SwapInterval = interval;
-}
-
-
-#ifdef EGL_MESA_screen_surface
-static EGLint
-_eglParseScreenSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
-{
- EGLint i, err = EGL_SUCCESS;
-
- if (!attrib_list)
- return EGL_SUCCESS;
-
- for (i = 0; attrib_list[i] != EGL_NONE; i++) {
- EGLint attr = attrib_list[i++];
- EGLint val = attrib_list[i];
-
- switch (attr) {
- case EGL_WIDTH:
- if (val < 0) {
- err = EGL_BAD_PARAMETER;
- break;
- }
- surf->Width = val;
- break;
- case EGL_HEIGHT:
- if (val < 0) {
- err = EGL_BAD_PARAMETER;
- break;
- }
- surf->Height = val;
- break;
- default:
- err = EGL_BAD_ATTRIBUTE;
- break;
- }
-
- if (err != EGL_SUCCESS) {
- _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
- break;
- }
- }
-
- return err;
-}
-#endif /* EGL_MESA_screen_surface */
-
-
/**
* Parse the list of surface attributes and return the proper error code.
*/
EGLint type = surf->Type;
EGLint texture_type = EGL_PBUFFER_BIT;
EGLint i, err = EGL_SUCCESS;
+ EGLint attr = EGL_NONE;
+ EGLint val = EGL_NONE;
if (!attrib_list)
return EGL_SUCCESS;
-#ifdef EGL_MESA_screen_surface
- if (type == EGL_SCREEN_BIT_MESA)
- return _eglParseScreenSurfaceAttribList(surf, attrib_list);
-#endif
-
if (dpy->Extensions.NOK_texture_from_pixmap)
texture_type |= EGL_PIXMAP_BIT;
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
- EGLint attr = attrib_list[i++];
- EGLint val = attrib_list[i];
+ attr = attrib_list[i++];
+ val = attrib_list[i];
switch (attr) {
/* common attributes */
+ case EGL_GL_COLORSPACE_KHR:
+ if (!dpy->Extensions.KHR_gl_colorspace) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ switch (val) {
+ case EGL_GL_COLORSPACE_SRGB_KHR:
+ case EGL_GL_COLORSPACE_LINEAR_KHR:
+ break;
+ default:
+ err = EGL_BAD_ATTRIBUTE;
+ }
+ if (err != EGL_SUCCESS)
+ break;
+ surf->GLColorspace = val;
+ break;
case EGL_VG_COLORSPACE:
switch (val) {
case EGL_VG_COLORSPACE_sRGB:
}
surf->RenderBuffer = val;
break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!dpy->Extensions.NV_post_sub_buffer ||
+ type != EGL_WINDOW_BIT) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+ if (val != EGL_TRUE && val != EGL_FALSE) {
+ err = EGL_BAD_PARAMETER;
+ break;
+ }
+ surf->PostSubBufferSupportedNV = val;
+ break;
/* pbuffer surface attributes */
case EGL_WIDTH:
if (type != EGL_PBUFFER_BIT) {
err = EGL_BAD_ATTRIBUTE;
break;
}
+
switch (val) {
case EGL_TEXTURE_RGB:
case EGL_TEXTURE_RGBA:
err = EGL_BAD_ATTRIBUTE;
break;
}
+
switch (val) {
case EGL_TEXTURE_2D:
case EGL_NO_TEXTURE:
break;
}
- if (err != EGL_SUCCESS) {
- _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
+ if (err != EGL_SUCCESS)
break;
+ }
+
+ if (err == EGL_SUCCESS && type == EGL_PBUFFER_BIT) {
+ if ((surf->TextureTarget == EGL_NO_TEXTURE && surf->TextureFormat != EGL_NO_TEXTURE) ||
+ (surf->TextureFormat == EGL_NO_TEXTURE && surf->TextureTarget != EGL_NO_TEXTURE)) {
+ attr = surf->TextureTarget == EGL_NO_TEXTURE ? EGL_TEXTURE_TARGET : EGL_TEXTURE_FORMAT;
+ err = EGL_BAD_MATCH;
}
}
+ if (err != EGL_SUCCESS)
+ _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr);
+
return err;
}
{
const char *func;
EGLint renderBuffer = EGL_BACK_BUFFER;
+ EGLint swapBehavior = EGL_BUFFER_DESTROYED;
EGLint err;
+ /* Swap behavior can be preserved only if config supports this. */
+ if (conf->SurfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)
+ swapBehavior = EGL_BUFFER_PRESERVED;
+
switch (type) {
case EGL_WINDOW_BIT:
func = "eglCreateWindowSurface";
+ swapBehavior = EGL_BUFFER_DESTROYED;
break;
case EGL_PIXMAP_BIT:
func = "eglCreatePixmapSurface";
case EGL_PBUFFER_BIT:
func = "eglCreatePBufferSurface";
break;
-#ifdef EGL_MESA_screen_surface
- case EGL_SCREEN_BIT_MESA:
- func = "eglCreateScreenSurface";
- renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */
- break;
-#endif
default:
_eglLog(_EGL_WARNING, "Bad type in _eglInitSurface");
return EGL_FALSE;
}
- if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
+ if ((conf->SurfaceType & type) == 0)
/* The config can't be used to create a surface of this type */
- _eglError(EGL_BAD_CONFIG, func);
- return EGL_FALSE;
- }
+ return _eglError(EGL_BAD_MATCH, func);
- memset(surf, 0, sizeof(_EGLSurface));
- surf->Resource.Display = dpy;
+ _eglInitResource(&surf->Resource, sizeof(*surf), dpy);
surf->Type = type;
surf->Config = conf;
+ surf->Lost = EGL_FALSE;
surf->Width = 0;
surf->Height = 0;
surf->RenderBuffer = renderBuffer;
surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
+ surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
surf->MipmapLevel = 0;
surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
- surf->SwapBehavior = EGL_BUFFER_DESTROYED;
+ surf->SwapBehavior = swapBehavior;
surf->HorizontalResolution = EGL_UNKNOWN;
surf->VerticalResolution = EGL_UNKNOWN;
surf->AspectRatio = EGL_UNKNOWN;
+ surf->PostSubBufferSupportedNV = EGL_FALSE;
+ surf->SetDamageRegionCalled = EGL_FALSE;
+ surf->BufferAgeRead = EGL_FALSE;
+
/* the default swap interval is 1 */
- _eglClampSwapInterval(surf, 1);
+ surf->SwapInterval = 1;
err = _eglParseSurfaceAttribList(surf, attrib_list);
if (err != EGL_SUCCESS)
return _eglError(err, func);
- return EGL_TRUE;
-}
-
+ /* if EGL_LARGEST_PBUFFER in use, clamp width and height */
+ if (surf->LargestPbuffer) {
+ surf->Width = MIN2(surf->Width, _EGL_MAX_PBUFFER_WIDTH);
+ surf->Height = MIN2(surf->Height, _EGL_MAX_PBUFFER_HEIGHT);
+ }
-EGLBoolean
-_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
-{
- /* Drivers have to do the actual buffer swap. */
return EGL_TRUE;
}
-EGLBoolean
-_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
- EGLNativePixmapType target)
-{
- /* copy surface to native pixmap */
- /* All implementation burdon for this is in the device driver */
- return EGL_FALSE;
-}
-
-
EGLBoolean
_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLint attribute, EGLint *value)
*value = surface->Height;
break;
case EGL_CONFIG_ID:
- *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
+ *value = surface->Config->ConfigID;
break;
case EGL_LARGEST_PBUFFER:
- *value = surface->LargestPbuffer;
+ if (surface->Type == EGL_PBUFFER_BIT)
+ *value = surface->LargestPbuffer;
break;
case EGL_TEXTURE_FORMAT:
/* texture attributes: only for pbuffers, no error otherwise */
case EGL_VG_COLORSPACE:
*value = surface->VGColorspace;
break;
+ case EGL_GL_COLORSPACE_KHR:
+ if (!dpy->Extensions.KHR_gl_colorspace)
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
+
+ *value = surface->GLColorspace;
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ *value = surface->PostSubBufferSupportedNV;
+ break;
+ case EGL_BUFFER_AGE_EXT:
+ if (!dpy->Extensions.EXT_buffer_age)
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
+
+ _EGLContext *ctx = _eglGetCurrentContext();
+ EGLint result = drv->API.QueryBufferAge(drv, dpy, surface);
+ /* error happened */
+ if (result < 0)
+ return EGL_FALSE;
+ if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
+ ctx->DrawSurface != surface)
+ return _eglError(EGL_BAD_SURFACE, "eglQuerySurface");
+
+ *value = result;
+ surface->BufferAgeRead = EGL_TRUE;
+ break;
default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
- return EGL_FALSE;
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
}
return EGL_TRUE;
}
-/**
- * Drivers should do a proper implementation.
- */
-_EGLSurface *
-_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- EGLNativeWindowType window, const EGLint *attrib_list)
-{
- return NULL;
-}
-
-
-/**
- * Drivers should do a proper implementation.
- */
-_EGLSurface *
-_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- EGLNativePixmapType pixmap, const EGLint *attrib_list)
-{
- return NULL;
-}
-
-
-/**
- * Drivers should do a proper implementation.
- */
-_EGLSurface *
-_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
- const EGLint *attrib_list)
-{
- return NULL;
-}
-
-
-/**
- * Default fallback routine - drivers should usually override this.
- */
-EGLBoolean
-_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
-{
- if (!_eglIsSurfaceBound(surf))
- free(surf);
- return EGL_TRUE;
-}
-
-
/**
* Default fallback routine - drivers might override this.
*/
{
EGLint confval;
EGLint err = EGL_SUCCESS;
+ EGLint all_es_bits = EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENGL_ES3_BIT_KHR;
switch (attribute) {
case EGL_MIPMAP_LEVEL:
- confval = GET_CONFIG_ATTRIB(surface->Config, EGL_RENDERABLE_TYPE);
- if (!(confval & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT))) {
+ confval = surface->Config->RenderableType;
+ if (!(confval & all_es_bits)) {
err = EGL_BAD_PARAMETER;
break;
}
case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
break;
case EGL_MULTISAMPLE_RESOLVE_BOX:
- confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE);
+ confval = surface->Config->SurfaceType;
if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
err = EGL_BAD_MATCH;
break;
case EGL_BUFFER_DESTROYED:
break;
case EGL_BUFFER_PRESERVED:
- confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE);
+ confval = surface->Config->SurfaceType;
if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
err = EGL_BAD_MATCH;
break;
if (dpy->Extensions.NOK_texture_from_pixmap)
texture_type |= EGL_PIXMAP_BIT;
- if (!(surface->Type & texture_type)) {
- _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
- return EGL_FALSE;
- }
+ if (!(surface->Type & texture_type))
+ return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
- if (surface->TextureFormat == EGL_NO_TEXTURE) {
- _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- return EGL_FALSE;
- }
+ if (surface->TextureFormat == EGL_NO_TEXTURE)
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- if (surface->TextureTarget == EGL_NO_TEXTURE) {
- _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- return EGL_FALSE;
- }
+ if (surface->TextureTarget == EGL_NO_TEXTURE)
+ return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- if (buffer != EGL_BACK_BUFFER) {
- _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
- return EGL_FALSE;
- }
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
surface->BoundToTexture = EGL_TRUE;
return EGL_TRUE;
}
-
EGLBoolean
-_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
+_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint buffer)
{
/* Just do basic error checking and return success/fail.
* Drivers must implement the real stuff.
*/
- if (surface->Type != EGL_PBUFFER_BIT) {
- _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
- return EGL_FALSE;
- }
+ EGLint texture_type = EGL_PBUFFER_BIT;
- if (surface->TextureFormat == EGL_NO_TEXTURE) {
- _eglError(EGL_BAD_MATCH, "eglBindTexImage");
- return EGL_FALSE;
- }
+ if (surf == EGL_NO_SURFACE)
+ return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
- if (buffer != EGL_BACK_BUFFER) {
- _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
- return EGL_FALSE;
+ if (!surf->BoundToTexture)
+ {
+ /* Not an error, simply nothing to do */
+ return EGL_TRUE;
}
- if (!surface->BoundToTexture) {
- _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
- return EGL_FALSE;
- }
+ if (surf->TextureFormat == EGL_NO_TEXTURE)
+ return _eglError(EGL_BAD_MATCH, "eglReleaseTexImage");
- surface->BoundToTexture = EGL_FALSE;
+ if (buffer != EGL_BACK_BUFFER)
+ return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+
+ if (dpy->Extensions.NOK_texture_from_pixmap)
+ texture_type |= EGL_PIXMAP_BIT;
+
+ if (!(surf->Type & texture_type))
+ return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+
+ surf->BoundToTexture = EGL_FALSE;
return EGL_TRUE;
}
_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
EGLint interval)
{
- _eglClampSwapInterval(surf, interval);
return EGL_TRUE;
}
-
-
-#ifdef EGL_VERSION_1_2
-
-/**
- * Example function - drivers should do a proper implementation.
- */
-_EGLSurface *
-_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy,
- EGLenum buftype, EGLClientBuffer buffer,
- _EGLConfig *conf, const EGLint *attrib_list)
-{
- if (buftype != EGL_OPENVG_IMAGE) {
- _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer");
- return NULL;
- }
-
- return NULL;
-}
-
-#endif /* EGL_VERSION_1_2 */