Hello again!
I've managed to create the patch, it should be in the attachment.
Here are the explanations:
* Since only 24-bit XVisualInfo's were provided, I've changed the
__vglConfigDepth function in glxvisual.cpp to provide depth for the
visual that is corresponding to the FBConfig on the local display. The
modified version returns 32-bit visuals when needed.
* The faked implementation of EXT_texture_from_pixmap OpenGL extension
didn't work correctly, because the extension can only work with
GLXPixmaps, not with windows and not with pbuffers. The approach I used
is: fake XCompositeNameWindowPixmap, XCreatePixmap and XFreePixmap to
know when the original pixmap is created, store the information on the
created pixmap (with Window form XCompositeNameWindowPixmap) to use
later. Then if and when the pixmap created previously is used to create
a GLXPixmap, add other values to the stored information and create
another pixmap using XShm. When this GLXPixmap is being used for
glXBindTexImageEXT the original pixmap's contents are copied to the shm
segment to be made available to the local display's XServer. The texture
is then filled with data using the shm address. If the FBConfig is
y-inverted (GLX_Y_INVERTED), the function modifies the GL_TEXTURE matrix
to invert the texture coordinates. When glXReleaseTexImageEXT is called
and if the FBConfig is inverted, the GL_TEXTURE matrix is restored to
the previous state.
This part covers faker-glx.cpp, faker.cpp, faker-sym.h, faker-sym.cpp,
faker-mapfile.c and the newly added shmpixmap.h that provides storage
for the mentioned pixmaps.
The patch should be applied to "vgl" directory (which contains "rr")
But these additions are not enough to run KDE4 in OpenGL mode. You also
have to do the following:
* Go to System Settings->Desktop->Advanced.
* Check "Disable functionality checks" checkbox.
* Select "Texture From Pixmap" OpenGL mode.
Also I didn't find how to enable the option called "glStrictBinding", so
I had to simply cut it from kwin/scene_opengl.cpp file from
kdebase-workspace.
If everything mentioned above is accomplished, you should be able to run
KDE4 in OpenGL mode over VNC.
I would be very grateful if somebody gave me feedback on that patch :)
P.S. I've been able to test it on Code2Duo P8400/2048 RAM/NV 9600 GS,
Debian 5.0
diff --git a/rr/faker-glx.cpp b/rr/faker-glx.cpp
index b74f320..1d60f19 100644
--- a/rr/faker-glx.cpp
+++ b/rr/faker-glx.cpp
@@ -14,6 +14,8 @@
*/
#include "faker-sym.h"
+#include "shmpixmap.h"
+#include </usr/include/GL/glu.h>
#define prargd(a) rrout.print("%s=0x%.8lx(%s) ", #a, (unsigned long)a,
a?DisplayString(a):"NULL")
#define prargx(a) rrout.print("%s=0x%.8lx ", #a, (unsigned long)a)
@@ -773,13 +775,51 @@ Bool glXResetFrameCountNV(Display *dpy, int screen)
void glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
const int *attrib_list)
{
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForGLXPixmap( drawable );
+ if( info != NULL )
+ {
+ int fmt = info->depth == 32 ? GL_RGBA : GL_RGB;
+ _XCopyArea( info->display, info->originalPixmap,
info->sharedPixmap, info->gc, 0, 0, info->width, info->height, 0, 0 );
+ XSync( info->display, False );
+ glTexImage2D( GL_TEXTURE_2D, 0, fmt, info->width, info->height,
0, GL_BGRA, GL_UNSIGNED_BYTE, info->shmInfo.shmaddr );
+
+ if( info->invert )
+ {
+ glGetDoublev( GL_TEXTURE_MATRIX, info->matrix );
+ double m[ 16 ] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, -1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 1.0, 0.0, 1.0
+ };
+ glMatrixMode( GL_TEXTURE );
+ glLoadMatrixd( m );
+ glMatrixMode( GL_MODELVIEW );
+ }
+
+ return;
+ }
GLXDrawable dr = ServerDrawable( dpy, drawable );
_glXBindTexImageEXT(_localdpy, dr, buffer, attrib_list);
}
void glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
{
- _glXReleaseTexImageEXT(_localdpy, ServerDrawable(dpy, drawable),
buffer);
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForGLXPixmap( drawable );
+ if( info != NULL )
+ {
+ if( info->invert )
+ {
+ glMatrixMode( GL_TEXTURE );
+ glLoadMatrixd( info->matrix );
+ glMatrixMode( GL_MODELVIEW );
+ }
+ return;
+ }
+ else
+ _glXReleaseTexImageEXT(_localdpy, ServerDrawable(dpy,
drawable), buffer);
}
#define checkfaked(f) if(!strcmp((char *)procName, #f)) retval=(void
(*)(void))f;
diff --git a/rr/faker-mapfile.c b/rr/faker-mapfile.c
index 2b56f33..800fab2 100755
--- a/rr/faker-mapfile.c
+++ b/rr/faker-mapfile.c
@@ -125,6 +125,9 @@
XResizeWindow;
XServerVendor;
XWindowEvent;
+ XFreePixmap;
+ XCreatePixmap;
+ XCompositeNameWindowPixmap;
#ifdef sparc
XSolarisGetVisualGamma;
#endif
diff --git a/rr/faker-sym.cpp b/rr/faker-sym.cpp
index 3bf201a..2b50ba0 100644
--- a/rr/faker-sym.cpp
+++ b/rr/faker-sym.cpp
@@ -35,6 +35,7 @@ static void *loadsym(void *dllhnd, const char *symbol, int
quiet)
static void *gldllhnd=NULL;
static void *x11dllhnd=NULL;
+static void* xcompdllhnd=NULL;
void __vgl_loaddlsymbols(void)
{
@@ -144,6 +145,20 @@ void __vgl_loadsymbols(void)
__vgl_safeexit(1);
}
}
+
+ dllhnd=_vgl_dlopen( "libXcomposite.so", RTLD_NOW);
+ if(!dllhnd)
+ {
+ rrout.print("[VGL] ERROR: Could not open
libXcomposite.so\n[VGL] %s\n",
+ dlerror());
+ __vgl_safeexit(1);
+ }
+ else xcompdllhnd=dllhnd;
+ if(__vgl_loadxcompsymbols(dllhnd)<0)
+ {
+ rrout.print("[VGL] ERROR: Could not load Xcomposite symbols
from libXcomposite.\n");
+ __vgl_safeexit(1);
+ }
}
static int __vgl_loadglsymbols(void *dllhnd)
@@ -272,6 +287,16 @@ static int __vgl_loadx11symbols(void *dllhnd)
lsym(XResizeWindow);
lsym(XServerVendor);
lsym(XWindowEvent);
+ lsym(XFreePixmap);
+ lsym(XCreatePixmap);
+ return 0;
+}
+
+static int __vgl_loadxcompsymbols(void *dllhnd)
+{
+ dlerror(); // Clear error state
+
+ lsym(XCompositeNameWindowPixmap);
return 0;
}
@@ -279,4 +304,5 @@ void __vgl_unloadsymbols(void)
{
if(gldllhnd) dlclose(gldllhnd);
if(x11dllhnd) dlclose(x11dllhnd);
+ if(xcompdllhnd) dlclose( xcompdllhnd );
}
diff --git a/rr/faker-sym.h b/rr/faker-sym.h
index 4fb75db..ed239f7 100644
--- a/rr/faker-sym.h
+++ b/rr/faker-sym.h
@@ -396,6 +396,11 @@ funcdef1(char *, XServerVendor, Display *, dpy, return);
funcdef4(int, XWindowEvent, Display *, dpy, Window, win, long, event_mask,
XEvent *, xe, return);
+funcdef2(int, XFreePixmap, Display*, dpy, Pixmap, pixmap, return);
+
+funcdef5( Pixmap, XCreatePixmap, Display*, dpy, Drawable, d, unsigned int,
width, unsigned int, height, unsigned int, depth, return );
+
+funcdef2( Pixmap, XCompositeNameWindowPixmap, Display*, dpy, Window, window,
return );
// From dlfaker
diff --git a/rr/faker.cpp b/rr/faker.cpp
index cb519e3..054d3ee 100644
--- a/rr/faker.cpp
+++ b/rr/faker.cpp
@@ -36,6 +36,10 @@
#include "vglconfigstart.h"
#include <sys/types.h>
#include <unistd.h>
+#include "shmpixmap.h"
+#include <iostream>
+#include </usr/include/GL/glxext.h>
+#include <X11/extensions/Xcomposite.h>
#ifdef SUNOGL
extern "C" {
@@ -103,6 +107,8 @@ static void __vgl_cleanup(void)
if(glxdhash::isalloc()) glxdh.killhash();
if(winhash::isalloc()) winh.killhash();
+ ShmPixmapStorage::killInstance();
+
__vgl_unloadsymbols();
}
@@ -390,6 +396,48 @@ Display *XOpenDisplay(_Xconst char* name)
return dpy;
}
+int XFreePixmap ( Display* dpy, Pixmap pixmap )
+{
+ int ret = _XFreePixmap( dpy, pixmap );
+
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForPixmap( pixmap );
+ if( info != NULL )
+ s->removeInfo( info );
+
+ return ret;
+}
+
+Pixmap XCreatePixmap ( Display* dpy, Drawable d, unsigned int width,
unsigned int height, unsigned int depth )
+{
+ Pixmap ret = _XCreatePixmap( dpy, d, width, height, depth );
+
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ s->addInfo( dpy, None, width, height, depth, ret );
+
+ return ret;
+}
+
+Pixmap XCompositeNameWindowPixmap( Display* dpy, Window window )
+{
+ Pixmap ret = _XCompositeNameWindowPixmap( dpy, window );
+
+ Window root;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border;
+ unsigned int depth;
+
+ XGetGeometry( dpy, window, &root, &x, &y, &width, &height, &border,
&depth );
+
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ s->addInfo( dpy, window, width, height, depth, ret );
+
+ return ret;
+}
+
Window XCreateWindow(Display *dpy, Window parent, int x, int y,
unsigned int width, unsigned int height, unsigned int border_width,
int depth, unsigned int c_class, Visual *visual, unsigned long
valuemask,
@@ -489,6 +537,18 @@ static void _HandleEvent(Display *dpy, XEvent *xe)
pbwin *pbw=NULL;
if(xe && xe->type==ConfigureNotify)
{
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForWindow(
xe->xconfigure.window );
+ if( info != NULL )
+ {
+ if( info->shmCreated )
+ s->resize( info, xe->xconfigure.width,
xe->xconfigure.height );
+ else
+ {
+ info->width = xe->xconfigure.width;
+ info->height = xe->xconfigure.height;
+ }
+ }
if(winh.findpb(dpy, xe->xconfigure.window, pbw))
{
opentrace(_HandleEvent);
prargi(xe->xconfigure.width);
@@ -593,6 +653,35 @@ Bool XCheckTypedWindowEvent(Display *dpy, Window win, int
event_type, XEvent *xe
int XConfigureWindow(Display *dpy, Window win, unsigned int value_mask,
XWindowChanges *values)
{
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForWindow( win );
+ if( info != NULL && values != NULL )
+ {
+ int width = 0;
+ int height = 0;
+ if( value_mask & CWWidth )
+ width = values->width;
+ if( value_mask & CWHeight )
+ height = values->height;
+ if( info->shmCreated )
+ {
+ if( width != 0 || height != 0 )
+ {
+ if( width == 0 )
+ width = info->width;
+ if( height == 0 )
+ height = info->height;
+ s->resize( info, width, height );
+ return _XConfigureWindow( dpy, win, value_mask,
values );
+ }
+ }
+ else
+ {
+ info->width = width;
+ info->height = height;
+ }
+ }
+
int retval=0;
TRY();
@@ -613,6 +702,22 @@ int XConfigureWindow(Display *dpy, Window win, unsigned
int value_mask, XWindowC
int XResizeWindow(Display *dpy, Window win, unsigned int width, unsigned int
height)
{
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForWindow( win );
+ if( info != NULL )
+ {
+ if( info->shmCreated )
+ {
+ s->resize( info, width, height );
+ return _XResizeWindow( dpy, win, width, height );
+ }
+ else
+ {
+ info->width = width;
+ info->height = height;
+ }
+ }
+
int retval=0;
TRY();
@@ -631,6 +736,23 @@ int XResizeWindow(Display *dpy, Window win, unsigned int
width, unsigned int hei
int XMoveResizeWindow(Display *dpy, Window win, int x, int y, unsigned int
width, unsigned int height)
{
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForWindow( win );
+ if( info != NULL )
+ {
+ if( info->shmCreated )
+ {
+ s->resize( info, width, height );
+ return _XMoveResizeWindow( dpy, win, x, y, width,
height );
+ }
+ else
+ {
+ info->width = width;
+ info->height = height;
+ }
+ }
+
+
int retval=0;
TRY();
@@ -668,6 +790,15 @@ int XCopyArea(Display *dpy, Drawable src, Drawable dst, GC
gc, int src_x, int sr
return retval;
}
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForPixmap( dst );
+ if( info == NULL )
+ info = s->getInfoForGLXPixmap( dst );
+ if( info == NULL )
+ info = s->getInfoForWindow( dst );
+ if( info != NULL )
+ return _XCopyArea( dpy, src, dst, gc, src_x, src_y, w, h,
dest_x, dest_y );
+
opentrace(XCopyArea); prargd(dpy); prargx(src); prargx(dst);
prargx(gc);
prargi(src_x); prargi(src_y); prargi(w); prargi(h);
prargi(dest_x);
prargi(dest_y); prargx(read); prargx(draw); starttrace();
@@ -1335,6 +1466,17 @@ GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig
config, Pixmap pm, const int
CATCH();
+ ShmPixmapStorage* s = ShmPixmapStorage::getInstance();
+ ShmPixmapInfo* info = s->getInfoForPixmap( pm );
+ if( info != NULL )
+ {
+ int value = 0;
+ _glXGetFBConfigAttrib( dpy, config, 0x20D4, &value );
+ s->addShm( info );
+ info->glxPixmap = drawable;
+ info->invert = ( value != 0 );
+ }
+
return drawable;
}
diff --git a/rr/glxvisual.cpp b/rr/glxvisual.cpp
index 599ac33..99ca8df 100644
--- a/rr/glxvisual.cpp
+++ b/rr/glxvisual.cpp
@@ -422,11 +422,18 @@ int __vglConfigDepth(GLXFBConfig c)
render_type=__vglServerVisualAttrib(c, GLX_RENDER_TYPE);
if(render_type==GLX_RGBA_BIT)
{
- r=__vglServerVisualAttrib(c, GLX_RED_SIZE);
+ /* r=__vglServerVisualAttrib(c, GLX_RED_SIZE);
g=__vglServerVisualAttrib(c, GLX_GREEN_SIZE);
b=__vglServerVisualAttrib(c, GLX_BLUE_SIZE);
depth=r+g+b;
if(depth<8) depth=1; // Monochrome
+ */
+
+ XVisualInfo* info = glXGetVisualFromFBConfig( _localdpy, c );
+
+ if( info )
+ return info->depth;
+ depth = 1;
}
else
{
diff --git a/rr/shmpixmap.h b/rr/shmpixmap.h
new file mode 100644
index 0000000..3aa8717
--- /dev/null
+++ b/rr/shmpixmap.h
@@ -0,0 +1,185 @@
+#pragma once
+
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#include <GL/gl.h>
+
+#include <list>
+#include <iostream>
+
+extern Display* _localdpy;
+
+struct ShmPixmapInfo
+{
+ friend class ShmPixmapStorage;
+
+ Display* display;
+ XShmSegmentInfo shmInfo;
+ Pixmap originalPixmap;
+ GC gc;
+ Pixmap sharedPixmap;
+ GLXPixmap glxPixmap;
+ int width;
+ int height;
+ int depth;
+ Window win;
+ bool shmCreated;
+ double matrix[ 16 ];
+ bool invert;
+};
+
+class ShmPixmapStorage
+{
+private:
+ typedef std::list< ShmPixmapInfo* > Storage;
+ typedef std::list< ShmPixmapInfo* >::iterator Iterator;
+
+private:
+ ShmPixmapStorage()
+ {
+ instance_ = this;
+ }
+ ~ShmPixmapStorage()
+ {
+ instance_ = NULL;
+ }
+
+public:
+ ShmPixmapInfo* getInfoForPixmap ( Pixmap value )
+ {
+ for( Iterator i = storage_.begin(); i != storage_.end(); ++ i )
+ if( ( *i )->originalPixmap == value )
+ return ( *i );
+
+ return NULL;
+ }
+ ShmPixmapInfo* getInfoForGLXPixmap ( GLXPixmap value )
+ {
+ for( Iterator i = storage_.begin(); i != storage_.end(); ++ i )
+ if( ( *i )->glxPixmap == value )
+ return ( *i );
+
+ return NULL;
+ }
+ ShmPixmapInfo* getInfoForWindow ( Window value )
+ {
+ for( Iterator i = storage_.begin(); i != storage_.end(); ++ i )
+ if( ( *i )->win == value )
+ return ( *i );
+
+ return NULL;
+ }
+
+ void addInfo ( Display* dpy, Window window, int width, int height,
int depth, Pixmap value )
+ {
+ ShmPixmapInfo* info = new ShmPixmapInfo;
+ info->display = dpy;
+ info->win = window;
+ info->width = width;
+ info->height = height;
+ info->depth = depth;
+ info->originalPixmap = value;
+ info->shmCreated = false;
+ info->invert = false;
+ storage_.push_back( info );
+ }
+
+ void addShm ( ShmPixmapInfo* value )
+ {
+ XGCValues gcv;
+ unsigned long size = value->width * value->height *
value->depth;
+ value->shmInfo.shmid = shmget( IPC_PRIVATE, size, IPC_CREAT
| 0777 );
+ value->shmInfo.shmaddr = ( char* )( shmat(
value->shmInfo.shmid, 0, 0 ) );
+ value->shmInfo.readOnly = False;
+ XShmAttach( value->display, &value->shmInfo );
+ value->gc = XCreateGC( value->display,
value->originalPixmap, 0, &gcv );
+ value->sharedPixmap = XShmCreatePixmap
+ (
+ value->display,
+ value->originalPixmap,
+ value->shmInfo.shmaddr,
+ &value->shmInfo,
+ value->width,
+ value->height,
+ value->depth
+ );
+ XSync( value->display, False );
+ value->shmCreated = true;
+ }
+
+ void resize ( ShmPixmapInfo* value, unsigned int width,
unsigned int height )
+ {
+ value->width = width;
+ value->height = height;
+
+ if( value->shmCreated )
+ {
+ XShmDetach( value->display, &value->shmInfo );
+ _XFreePixmap( value->display, value->sharedPixmap );
+ shmdt( value->shmInfo.shmaddr );
+ shmctl( value->shmInfo.shmid, IPC_RMID, 0 );
+ }
+
+ unsigned long size = value->width * value->height *
value->depth;
+ value->shmInfo.shmid = shmget( IPC_PRIVATE, size, IPC_CREAT
| 0777 );
+ value->shmInfo.shmaddr = ( char* )( shmat(
value->shmInfo.shmid, 0, 0 ) );
+ value->shmInfo.readOnly = False;
+ XShmAttach( value->display, &value->shmInfo );
+ value->sharedPixmap = XShmCreatePixmap
+ (
+ value->display,
+ value->originalPixmap,
+ value->shmInfo.shmaddr,
+ &value->shmInfo,
+ value->width,
+ value->height,
+ value->depth
+ );
+ XSync( value->display, False );
+ value->shmCreated = true;
+ }
+
+ void removeInfo ( ShmPixmapInfo* value )
+ {
+ Iterator i;
+ for( i = storage_.begin(); i != storage_.end(); ++ i )
+ if( ( *i ) == value )
+ break;
+
+ if( i == storage_.end() )
+ return;
+
+ storage_.erase( i );
+
+ if( value->shmCreated )
+ {
+ XShmDetach( value->display, &value->shmInfo );
+ _XFreePixmap( value->display, value->sharedPixmap );
+ shmdt( value->shmInfo.shmaddr );
+ shmctl( value->shmInfo.shmid, IPC_RMID, 0 );
+ }
+
+ delete value;
+ }
+
+ static ShmPixmapStorage* getInstance ()
+ {
+ if( instance_ == NULL )
+ instance_ = new ShmPixmapStorage();
+ return instance_;
+ }
+ static void killInstance ()
+ {
+ if( instance_ != NULL )
+ {
+ delete instance_;
+ instance_ = NULL;
+ }
+ }
+
+private:
+ static ShmPixmapStorage* instance_;
+ Storage storage_;
+};
+
+ShmPixmapStorage* ShmPixmapStorage::instance_ = NULL;
------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
VirtualGL-Users mailing list
VirtualGL-Users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/virtualgl-users