/** * Surface-related functions. */ #include #include #include #include "egldisplay.h" #include "eglcontext.h" #include "eglconfig.h" #include "eglcurrent.h" #include "egllog.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; } /** * Parse the list of surface attributes and return the proper error code. */ static EGLint _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) { EGLint type = surf->Type; 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) { #ifdef EGL_VERSION_1_3 /* common (except for screen surfaces) attributes */ case EGL_VG_COLORSPACE: if (type == EGL_SCREEN_BIT_MESA) { err = EGL_BAD_ATTRIBUTE; break; } switch (val) { case EGL_VG_COLORSPACE_sRGB: case EGL_VG_COLORSPACE_LINEAR: break; default: err = EGL_BAD_ATTRIBUTE; break; } if (err != EGL_SUCCESS) break; surf->Colorspace = val; break; case EGL_VG_ALPHA_FORMAT: if (type == EGL_SCREEN_BIT_MESA) { err = EGL_BAD_ATTRIBUTE; break; } switch (val) { case EGL_VG_ALPHA_FORMAT_NONPRE: case EGL_VG_ALPHA_FORMAT_PRE: break; default: err = EGL_BAD_ATTRIBUTE; break; } if (err != EGL_SUCCESS) break; surf->AlphaFormat = val; break; /* window surface attributes */ case EGL_RENDER_BUFFER: if (type != EGL_WINDOW_BIT) { err = EGL_BAD_ATTRIBUTE; break; } if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) { err = EGL_BAD_ATTRIBUTE; break; } surf->RenderBuffer = val; break; #endif /* EGL_VERSION_1_3 */ /* pbuffer surface attributes */ case EGL_WIDTH: if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { err = EGL_BAD_ATTRIBUTE; break; } if (val < 0) { err = EGL_BAD_PARAMETER; break; } surf->Width = val; break; case EGL_HEIGHT: if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { err = EGL_BAD_ATTRIBUTE; break; } if (val < 0) { err = EGL_BAD_PARAMETER; break; } surf->Height = val; break; case EGL_LARGEST_PBUFFER: if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } break; case EGL_TEXTURE_FORMAT: if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } surf->TextureFormat = val; break; case EGL_TEXTURE_TARGET: if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } surf->TextureTarget = val; break; case EGL_MIPMAP_TEXTURE: if (type != EGL_PBUFFER_BIT) { err = EGL_BAD_ATTRIBUTE; break; } surf->MipmapTexture = val; break; /* no pixmap surface specific attributes */ default: err = EGL_BAD_ATTRIBUTE; break; } if (err != EGL_SUCCESS) { _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr); break; } } return err; } /** * Do error check on parameters and initialize the given _EGLSurface object. * \return EGL_TRUE if no errors, EGL_FALSE otherwise. */ EGLBoolean _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, _EGLConfig *conf, const EGLint *attrib_list) { const char *func; EGLint renderBuffer = EGL_BACK_BUFFER; EGLint err; switch (type) { case EGL_WINDOW_BIT: func = "eglCreateWindowSurface"; break; case EGL_PIXMAP_BIT: func = "eglCreatePixmapSurface"; renderBuffer = EGL_SINGLE_BUFFER; break; case EGL_PBUFFER_BIT: func = "eglCreatePBufferSurface"; break; case EGL_SCREEN_BIT_MESA: func = "eglCreateScreenSurface"; renderBuffer = EGL_SINGLE_BUFFER; /* XXX correct? */ break; default: _eglLog(_EGL_WARNING, "Bad type in _eglInitSurface"); return EGL_FALSE; } if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) { /* The config can't be used to create a surface of this type */ _eglError(EGL_BAD_CONFIG, func); return EGL_FALSE; } memset(surf, 0, sizeof(_EGLSurface)); surf->Type = type; surf->Config = conf; surf->Width = 0; surf->Height = 0; surf->TextureFormat = EGL_NO_TEXTURE; surf->TextureTarget = EGL_NO_TEXTURE; surf->MipmapTexture = EGL_FALSE; surf->MipmapLevel = 0; /* the default swap interval is 1 */ _eglClampSwapInterval(surf, 1); #ifdef EGL_VERSION_1_2 surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */ surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */ surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */ surf->AspectRatio = EGL_UNKNOWN; /* set by caller */ surf->RenderBuffer = renderBuffer; surf->AlphaFormat = EGL_ALPHA_FORMAT_NONPRE; surf->Colorspace = EGL_COLORSPACE_sRGB; #endif err = _eglParseSurfaceAttribList(surf, attrib_list); if (err != EGL_SUCCESS) return _eglError(err, func); return EGL_TRUE; } 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) { switch (attribute) { case EGL_WIDTH: *value = surface->Width; return EGL_TRUE; case EGL_HEIGHT: *value = surface->Height; return EGL_TRUE; case EGL_CONFIG_ID: *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID); return EGL_TRUE; case EGL_LARGEST_PBUFFER: *value = dpy->LargestPbuffer; return EGL_TRUE; case EGL_SURFACE_TYPE: *value = surface->Type; return EGL_TRUE; #ifdef EGL_VERSION_1_1 case EGL_TEXTURE_FORMAT: /* texture attributes: only for pbuffers, no error otherwise */ if (surface->Type == EGL_PBUFFER_BIT) *value = surface->TextureFormat; return EGL_TRUE; case EGL_TEXTURE_TARGET: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->TextureTarget; return EGL_TRUE; case EGL_MIPMAP_TEXTURE: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->MipmapTexture; return EGL_TRUE; case EGL_MIPMAP_LEVEL: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->MipmapLevel; return EGL_TRUE; #endif /* EGL_VERSION_1_1 */ #ifdef EGL_VERSION_1_2 case EGL_SWAP_BEHAVIOR: *value = surface->SwapBehavior; return EGL_TRUE; case EGL_RENDER_BUFFER: *value = surface->RenderBuffer; return EGL_TRUE; case EGL_PIXEL_ASPECT_RATIO: *value = surface->AspectRatio; return EGL_TRUE; case EGL_HORIZONTAL_RESOLUTION: *value = surface->HorizontalResolution; return EGL_TRUE; case EGL_VERTICAL_RESOLUTION: *value = surface->VerticalResolution; return EGL_TRUE; case EGL_ALPHA_FORMAT: *value = surface->AlphaFormat; return EGL_TRUE; case EGL_COLORSPACE: *value = surface->Colorspace; return EGL_TRUE; #endif /* EGL_VERSION_1_2 */ default: _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); return EGL_FALSE; } } /** * 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. */ EGLBoolean _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value) { switch (attribute) { case EGL_MIPMAP_LEVEL: surface->MipmapLevel = value; break; default: _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib"); return EGL_FALSE; } return EGL_TRUE; } EGLBoolean _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, 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; } if (surface->TextureFormat == EGL_NO_TEXTURE) { _eglError(EGL_BAD_MATCH, "eglBindTexImage"); return EGL_FALSE; } if (buffer != EGL_BACK_BUFFER) { _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); return EGL_FALSE; } surface->BoundToTexture = EGL_TRUE; return EGL_TRUE; } EGLBoolean _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, 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; } if (surface->TextureFormat == EGL_NO_TEXTURE) { _eglError(EGL_BAD_MATCH, "eglBindTexImage"); return EGL_FALSE; } if (buffer != EGL_BACK_BUFFER) { _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); return EGL_FALSE; } if (!surface->BoundToTexture) { _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); return EGL_FALSE; } surface->BoundToTexture = EGL_FALSE; return EGL_TRUE; } EGLBoolean _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 */