From fd54564f78d4aeae2c39ada7502ec659c14b3eca Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 19 May 2007 08:27:35 -0600 Subject: [PATCH] Implement GLX_EXT_texture_from_pixmap. Could be done more efficiently... but works. --- src/mesa/drivers/x11/fakeglx.c | 186 +++++++++++++++++++++++-- src/mesa/drivers/x11/glxapi.c | 32 ++++- src/mesa/drivers/x11/glxapi.h | 5 + src/mesa/drivers/x11/xm_api.c | 247 +++++++++++++++++++++++++++++++-- src/mesa/drivers/x11/xmesaP.h | 9 +- 5 files changed, 454 insertions(+), 25 deletions(-) diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index 86a4deabc67..ef22a3f03eb 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul 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"), @@ -78,6 +78,7 @@ "GLX_MESA_pixmap_colormap " \ "GLX_MESA_release_buffers " \ "GLX_ARB_get_proc_address " \ + "GLX_EXT_texture_from_pixmap " \ "GLX_EXT_visual_info " \ "GLX_EXT_visual_rating " \ /*"GLX_SGI_video_sync "*/ \ @@ -1223,6 +1224,30 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) /* ignore */ break; +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + parselist++; + if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT)) { + /* invalid bit */ + return NULL; + } + break; + case GLX_Y_INVERTED_EXT: + parselist++; /*skip*/ + break; +#endif + case None: /* end of list */ break; @@ -1878,6 +1903,27 @@ get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) *value = xmvis->visinfo->visualid; break; +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + /* XXX review */ + *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value = (GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ + break; + case GLX_Y_INVERTED_EXT: + *value = False; /*XXX*/ + break; +#endif + default: return GLX_BAD_ATTRIBUTE; } @@ -2145,16 +2191,102 @@ Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, { XMesaVisual v = (XMesaVisual) config; XMesaBuffer b; - - (void) dpy; - (void) config; - (void) pixmap; - (void) attribList; /* Ignored in GLX 1.3 */ + const int *attr; + int target = 0, format = 0, mipmap = 0; + int value; if (!dpy || !config || !pixmap) return 0; - b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + for (attr = attribList; *attr; attr++) { + switch (*attr) { + case GLX_TEXTURE_FORMAT_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_FORMAT_NONE_EXT: + case GLX_TEXTURE_FORMAT_RGB_EXT: + case GLX_TEXTURE_FORMAT_RGBA_EXT: + format = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_TEXTURE_TARGET_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_1D_EXT: + case GLX_TEXTURE_2D_EXT: + case GLX_TEXTURE_RECTANGLE_EXT: + target = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_MIPMAP_TEXTURE_EXT: + attr++; + if (*attr) + mipmap = 1; + break; + default: + /* error */ + return 0; + } + } + + if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (mipmap) { + if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_1D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + else if (target == GLX_TEXTURE_2D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_RECTANGLE_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + + if (format || target || mipmap) { + /* texture from pixmap */ + b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); + } + else { + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + } if (!b) { return 0; } @@ -2260,8 +2392,20 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, case GLX_FBCONFIG_ID: *value = xmbuf->xm_visual->visinfo->visualid; return; +#ifdef GLX_EXT_texture_from_pixmap + case GLX_TEXTURE_FORMAT_EXT: + *value = xmbuf->TextureFormat; + break; + case GLX_TEXTURE_TARGET_EXT: + *value = xmbuf->TextureTarget; + break; + case GLX_MIPMAP_TEXTURE_EXT: + *value = xmbuf->TextureMipmap; + break; +#endif + default: - return; /* GLX_BAD_ATTRIBUTE? */ + return; /* raise BadValue error */ } } @@ -2854,6 +2998,26 @@ Fake_glXGetAGPOffsetMESA( const GLvoid *pointer ) } +/*** GLX_EXT_texture_from_pixmap ***/ + +static void +Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaBindTexImage(dpy, b, buffer, attrib_list); +} + +static void +Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaReleaseTexImage(dpy, b, buffer); +} + + /* silence warning */ extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); @@ -3009,5 +3173,9 @@ _mesa_GetGLXDispatchTable(void) /*** GLX_MESA_agp_offset ***/ glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA; + /*** GLX_EXT_texture_from_pixmap ***/ + glx.BindTexImageEXT = Fake_glXBindTexImageEXT; + glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; + return &glx; } diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c index 973f3940451..5f11c90c13c 100644 --- a/src/mesa/drivers/x11/glxapi.c +++ b/src/mesa/drivers/x11/glxapi.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul 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"), @@ -1104,6 +1104,27 @@ glXGetMemoryOffsetMESA(Display *dpy, int scrn, const void *pointer) } +/*** GLX_EXT_texture_from_pixmap */ + +void +glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (t) + t->BindTexImageEXT(dpy, drawable, buffer, attrib_list); +} + +void +glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (t) + t->ReleaseTexImageEXT(dpy, drawable, buffer); +} + /**********************************************************************/ /* GLX API management functions */ @@ -1147,6 +1168,9 @@ _glxapi_get_extensions(void) #endif #ifdef GLX_SGIX_pbuffer "GLX_SGIX_pbuffer", +#endif +#ifdef GLX_EXT_texture_from_pixmap, + "GLX_EXT_texture_from_pixmap", #endif NULL }; @@ -1333,6 +1357,10 @@ static struct name_address_pair GLX_functions[] = { { "glXFreeMemoryMESA", (__GLXextFuncPtr) glXFreeMemoryMESA }, { "glXGetMemoryOffsetMESA", (__GLXextFuncPtr) glXGetMemoryOffsetMESA }, + /*** GLX_EXT_texture_from_pixmap ***/ + { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, + { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, + { NULL, NULL } /* end of list */ }; diff --git a/src/mesa/drivers/x11/glxapi.h b/src/mesa/drivers/x11/glxapi.h index 3187534c9a3..37de81e55ac 100644 --- a/src/mesa/drivers/x11/glxapi.h +++ b/src/mesa/drivers/x11/glxapi.h @@ -196,6 +196,11 @@ struct _glxapi_table { /*** GLX_MESA_agp_offset ***/ GLuint (*GetAGPOffsetMESA)( const GLvoid *pointer ); + + /*** GLX_EXT_texture_from_pixmap ***/ + void (*BindTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list); + void (*ReleaseTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer); }; diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index a07d0a90cf3..edaa71508fc 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.2 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul 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"), @@ -72,6 +72,7 @@ #include "imports.h" #include "macros.h" #include "renderbuffer.h" +#include "teximage.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" #include "vbo/vbo.h" @@ -295,6 +296,19 @@ static GLboolean window_exists( XMesaDisplay *dpy, Window win ) #endif +static Status +get_drawable_size(Display *dpy, Drawable d, GLuint *width, GLuint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + /** * Return the size of the window (or pixmap) that corresponds to the @@ -310,22 +324,14 @@ xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b, *width = MIN2(b->frontxrb->drawable->width, MAX_WIDTH); *height = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT); #else - Window root; Status stat; - int xpos, ypos; - unsigned int w, h, bw, depth; _glthread_LOCK_MUTEX(_xmesa_lock); XSync(b->xm_visual->display, 0); /* added for Chromium */ - stat = XGetGeometry(dpy, b->frontxrb->pixmap, &root, &xpos, &ypos, - &w, &h, &bw, &depth); + stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height); _glthread_UNLOCK_MUTEX(_xmesa_lock); - if (stat) { - *width = w; - *height = h; - } - else { + if (!stat) { /* probably querying a window that's recently been destroyed */ _mesa_warning(NULL, "XGetGeometry failed!\n"); *width = *height = 1; @@ -431,6 +437,11 @@ create_xmesa_buffer(XMesaDrawable d, BufferType type, b->swAlpha, vis->mesa_visual.numAuxBuffers > 0 ); + /* GLX_EXT_texture_from_pixmap */ + b->TextureTarget = 0; + b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; + b->TextureMipmap = 0; + /* insert buffer into linked list */ b->Next = XMesaBufferList; XMesaBufferList = b; @@ -1673,6 +1684,67 @@ XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) } +/** + * For GLX_EXT_texture_from_pixmap + */ +XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, + XMesaColormap cmap, + int format, int target, int mipmap) +{ + GET_CURRENT_CONTEXT(ctx); + XMesaBuffer b; + GLuint width, height; + + assert(v); + + b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + /* get pixmap size, update framebuffer/renderbuffer dims */ + get_drawable_size(v->display, p, &width, &height); + _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); + + if (target == 0) { + /* examine dims */ + if (ctx->Extensions.ARB_texture_non_power_of_two) { + target = GLX_TEXTURE_2D_EXT; + } + else if ( _mesa_bitcount(width) == 1 + && _mesa_bitcount(height) == 1) { + /* power of two size */ + if (height == 1) { + target = GLX_TEXTURE_1D_EXT; + } + else { + target = GLX_TEXTURE_2D_EXT; + } + } + else if (ctx->Extensions.NV_texture_rectangle) { + target = GLX_TEXTURE_RECTANGLE_EXT; + } + else { + /* non power of two textures not supported */ + XMesaDestroyBuffer(b); + return 0; + } + } + + b->TextureTarget = target; + b->TextureFormat = format; + b->TextureMipmap = mipmap; + + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + (XMesaDrawable) p, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, @@ -2254,3 +2326,154 @@ XMesaResizeBuffers( XMesaBuffer b ) xmesa_check_and_update_buffer_size(xmctx, b); } + +static GLint +xbuffer_to_renderbuffer(int buffer) +{ + assert(MAX_AUX_BUFFERS <= 4); + + switch (buffer) { + case GLX_FRONT_LEFT_EXT: + return BUFFER_FRONT_LEFT; + case GLX_FRONT_RIGHT_EXT: + return BUFFER_FRONT_RIGHT; + case GLX_BACK_LEFT_EXT: + return BUFFER_BACK_LEFT; + case GLX_BACK_RIGHT_EXT: + return BUFFER_BACK_RIGHT; + case GLX_AUX0_EXT: + return BUFFER_AUX0; + case GLX_AUX1_EXT: + return BUFFER_AUX1; + case GLX_AUX2_EXT: + return BUFFER_AUX2; + case GLX_AUX3_EXT: + return BUFFER_AUX3; + case GLX_AUX4_EXT: + case GLX_AUX5_EXT: + case GLX_AUX6_EXT: + case GLX_AUX7_EXT: + case GLX_AUX8_EXT: + case GLX_AUX9_EXT: + default: + /* BadValue error */ + return -1; + } +} + + +PUBLIC void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list) +{ +#if 0 + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *texObj; +#endif + struct gl_renderbuffer *rb; + struct xmesa_renderbuffer *xrb; + GLint b; + XMesaImage *img; + GLboolean freeImg = GL_FALSE; + + b = xbuffer_to_renderbuffer(buffer); + if (b < 0) + return; + + if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) + return; /* BadMatch error */ + + rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; + if (!rb) { + /* invalid buffer */ + return; + } + xrb = xmesa_renderbuffer(rb); + +#if 0 + switch (drawable->TextureTarget) { + case GLX_TEXTURE_1D_EXT: + texObj = texUnit->Current1D; + break; + case GLX_TEXTURE_2D_EXT: + texObj = texUnit->Current2D; + break; + case GLX_TEXTURE_RECTANGLE_EXT: + texObj = texUnit->CurrentRect; + break; + default: + return; /* BadMatch error */ + } +#endif + + /* + * The following is a quick and simple way to implement + * BindTexImage. The better way is to write some new FetchTexel() + * functions which would extract texels from XImages. We'd still + * need to use XGetImage when texturing from a Pixmap (front buffer) + * but texturing from a back buffer (XImage) would avoid an image + * copy. + */ + + /* get XImage */ + if (xrb->pixmap) { + img = XGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, + AllPlanes, ZPixmap ); + freeImg = GL_TRUE; + } + else if (xrb->ximage) { + img = xrb->ximage; + } + + /* store the XImage as a new texture image */ + if (img) { + GLenum format, type, intFormat; + if (img->bits_per_pixel == 32) { + format = GL_BGRA; + type = GL_UNSIGNED_BYTE; + intFormat = GL_RGBA; + } + else if (img->bits_per_pixel == 24) { + format = GL_BGR; + type = GL_UNSIGNED_BYTE; + intFormat = GL_RGB; + } + else if (img->bits_per_pixel == 16) { + format = GL_BGR; + type = GL_UNSIGNED_SHORT_5_6_5; + intFormat = GL_RGB; + } + else { + _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); + return; + } + if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { + intFormat = GL_RGBA; + } + else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { + intFormat = GL_RGB; + } + + _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, + format, type, img->data); + + if (freeImg) { + XMesaDestroyImage(img); + } + } +} + + + +PUBLIC void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) +{ + const GLint b = xbuffer_to_renderbuffer(buffer); + if (b < 0) + return; + + /* no-op for now */ +} + diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h index 01988867476..e3d7cf381f7 100644 --- a/src/mesa/drivers/x11/xmesaP.h +++ b/src/mesa/drivers/x11/xmesaP.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.1 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul 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"), @@ -267,6 +267,11 @@ struct xmesa_buffer { fxMesaContext FXctx; #endif + /* GLX_EXT_texture_from_pixmap */ + GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */ + GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */ + GLint TextureMipmap; /** 0 or 1 */ + struct xmesa_buffer *Next; /* Linked list pointer: */ }; -- 2.30.2