egl: CreatePbufferSurface, Bind/ReleaseTexImage functions

This commit is contained in:
Brian Paul 2008-09-01 13:08:44 -06:00
parent b36f906573
commit 102529cf1b

View file

@ -64,6 +64,12 @@
#include "egllog.h"
#include "eglsurface.h"
#include <GL/gl.h>
typedef void (*glGetIntegerv_t)(GLenum, GLint *);
typedef void (*glBindTexture_t)(GLenum, GLuint);
typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint,
GLint, GLint, GLint);
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
@ -99,6 +105,8 @@ struct xdri_egl_context
_EGLContext Base; /**< base class */
__DRIcontext driContext;
GLint bound_tex_object;
};
@ -147,6 +155,11 @@ lookup_context(EGLContext c)
return (struct xdri_egl_context *) context;
}
static struct xdri_egl_context *
current_context(void)
{
return (struct xdri_egl_context *) _eglGetCurrentContext();
}
/** Map EGLConfig handle to xdri_egl_config object */
static struct xdri_egl_config *
@ -210,7 +223,8 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv)
SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
/* XXX only window rendering allowed ATM */
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
(EGL_WINDOW_BIT | EGL_PBUFFER_BIT));
/* XXX possibly other things to init... */
@ -854,6 +868,86 @@ xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
}
/**
* Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
*/
static EGLSurface
xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_surface *xdri_surf;
struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
int scrn = DefaultScreen(disp->Xdpy);
Window window;
xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
if (!xdri_surf)
return EGL_NO_SURFACE;
if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_PBUFFER_BIT,
config, attrib_list)) {
free(xdri_surf);
return EGL_FALSE;
}
/* Create a dummy X window */
{
Window root = RootWindow(disp->Xdpy, scrn);
XSetWindowAttributes attr;
XVisualInfo *visInfo, visTemplate;
unsigned mask;
int nvis;
visTemplate.visualid = xdri_config->mode->visualID;
visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis);
if (!visInfo) {
return EGL_NO_SURFACE;
}
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(disp->Xdpy, root,
visInfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
window = XCreateWindow(disp->Xdpy, root, 0, 0,
xdri_surf->Base.Width, xdri_surf->Base.Height,
0, visInfo->depth, InputOutput,
visInfo->visual, mask, &attr);
/*XMapWindow(disp->Xdpy, window);*/
XFree(visInfo);
/* set hints and properties */
/*
sizehints.width = xdri_surf->Base.Width;
sizehints.height = xdri_surf->Base.Height;
sizehints.flags = USPosition;
XSetNormalHints(disp->Xdpy, window, &sizehints);
*/
}
if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
free(xdri_surf);
return EGL_FALSE;
}
xdri_surf->driDrawable = window;
_eglSaveSurface(&xdri_surf->Base);
_eglLog(_EGL_DEBUG,
"XDRI: CreatePbufferSurface handle %d hDrawable %d",
_eglGetSurfaceHandle(&xdri_surf->Base),
(int) xdri_surf->hDrawable);
return _eglGetSurfaceHandle(&xdri_surf->Base);
}
static EGLBoolean
xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
@ -878,6 +972,137 @@ xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
}
static EGLBoolean
xdri_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
EGLint buffer)
{
typedef int (*bind_teximage)(__DRInativeDisplay *dpy,
__DRIid surface, __DRIscreen *psc,
int buffer, int target, int format,
int level, int mipmap);
bind_teximage egl_dri_bind_teximage;
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_context *xdri_ctx = current_context();
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
__DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
__GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
__DRIscreen *psc = &scrnConf->driScreen;
/* this call just does error checking */
if (!_eglBindTexImage(drv, dpy, surface, buffer)) {
return EGL_FALSE;
}
egl_dri_bind_teximage =
(bind_teximage) dlsym(NULL, "egl_dri_bind_teximage");
if (egl_dri_bind_teximage) {
return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc,
buffer,
xdri_surf->Base.TextureTarget,
xdri_surf->Base.TextureFormat,
xdri_surf->Base.MipmapLevel,
xdri_surf->Base.MipmapTexture);
}
else {
/* fallback path based on glCopyTexImage() */
/* Get/save currently bound 2D texobj name */
glGetIntegerv_t glGetIntegerv_func =
(glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
GLint curTexObj = 0;
if (glGetIntegerv_func) {
(*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj);
}
xdri_ctx->bound_tex_object = curTexObj;
}
return EGL_FALSE;
}
static EGLBoolean
xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
EGLint buffer)
{
typedef int (*release_teximage)(__DRInativeDisplay *dpy,
__DRIid surface, __DRIscreen *psc,
int buffer, int target, int format,
int level, int mipmap);
release_teximage egl_dri_release_teximage;
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct xdri_egl_context *xdri_ctx = current_context();
struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
__DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
__GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
__DRIscreen *psc = &scrnConf->driScreen;
/* this call just does error checking */
if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) {
return EGL_FALSE;
}
egl_dri_release_teximage =
(release_teximage) dlsym(NULL, "egl_dri_release_teximage");
if (egl_dri_release_teximage) {
return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc,
buffer,
xdri_surf->Base.TextureTarget,
xdri_surf->Base.TextureFormat,
xdri_surf->Base.MipmapLevel,
xdri_surf->Base.MipmapTexture);
}
else {
/* fallback path based on glCopyTexImage() */
glGetIntegerv_t glGetIntegerv_func =
(glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
glBindTexture_t glBindTexture_func =
(glBindTexture_t) dlsym(NULL, "glBindTexture");
glCopyTexImage2D_t glCopyTexImage2D_func =
(glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D");
GLint curTexObj;
GLenum intFormat;
GLint level, width, height;
if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA)
intFormat = GL_RGBA;
else
intFormat = GL_RGB;
level = xdri_surf->Base.MipmapLevel;
width = xdri_surf->Base.Width >> level;
height = xdri_surf->Base.Height >> level;
if (width > 0 && height > 0 &&
glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) {
glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj);
/* restore texobj from time of eglBindTexImage() call */
if (curTexObj != xdri_ctx->bound_tex_object)
glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object);
/* copy pbuffer image to texture */
glCopyTexImage2D_func(GL_TEXTURE_2D,
level,
intFormat,
0, 0, width, height, 0);
/* restore current texture */
if (curTexObj != xdri_ctx->bound_tex_object)
glBindTexture_func(GL_TEXTURE_2D, curTexObj);
}
xdri_ctx->bound_tex_object = -1;
}
return EGL_FALSE;
}
static EGLBoolean
xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
{
@ -931,7 +1156,10 @@ _eglMain(_EGLDisplay *disp, const char *args)
xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT |