Commits

Ivan Vučica committed d4fd996

Reorganization of configuration and addition of debug facilities. More sensible context switching, with some debug info. Context switching macros, for readability. Corrected where context switches are performed and cleaned up the mess a bit.

Unfortunately, this doesn't work yet, not on NVidia hardware, at least.

Comments (0)

Files changed (8)

+syntax: glob
+obj/*
+*.swp
+Fireplace.app/*

FPManagedWindow.m

 #import "FPManagedWindow.h"
 #import "FPEventLoop.h"
 #import "FPWindowManager.h"
+#import "GLConfiguration.h"
 
-#define SAFE_MODE 1
 
-#define USE_GLX1_3 1
+#define SWITCH_TO_STAGE_CONTEXT \
+	[mainDisplay makeCurrentContext:[_manager glxContext] \
+                               onWindow:[_manager stage] \
+                            contextName:@"Stage"];
+                          
+#define SWITCH_TO_WINDOW_CONTEXT \
+	[mainDisplay makeCurrentContext:[_manager glxContext] \
+                               onWindow:_window \
+                            contextName:[NSString stringWithFormat:@"Window %p", _window]];
 
-#define SWITCH_CONTEXTS 1
+#define PRINT_CURRENT_CONTEXT \
+	NSLog(@"=====>>> Current context: %@", [mainDisplay glxContextName]);
 
-#if !SAFE_MODE
-	#define HAVE_GL_COPY_TEX_IMAGE_2D 1
-	#define FORCE_TEXTURE_2D 0
-	#define USE_GLXBINDTEXIMAGE 1
-#else
-	#define HAVE_GL_COPY_TEX_IMAGE_2D 0
-	#define FORCE_TEXTURE_2D 0
-	#define USE_GLXBINDTEXIMAGE 0
-	#undef USE_GLX1_3
-	#define USE_GLX1_3 0
-#endif
 static int DamageNotify = -1;
 static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT = 0;
 static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT = 0;
 	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
 	Display * display = [mainDisplay display];
 	
+#if FORCE_TEXTURE_2D
 	const int pixmap_attribs[] = {
-		//GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+		GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+		GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
+		None
+	};
+#else
+	const int pixmap_attribs[] = {
 		GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_RECTANGLE_EXT,
 		GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
 		None
-	};            
-	NSLog(@"pixmap");
+	};
+#endif
+
+	NSLog(@"pixmap for %lp", _window);
 	_pixmap = XCompositeNameWindowPixmap (display, _window);
 	if(!_pixmap)
 		NSLog(@"Failed to make a pixmap");
+	XSync(display, None);
+	NSLog(@"Pixmap is %lp", _pixmap);
 NSLog(@"drawable");
 #if !USE_GLX1_3
 	_drawable = glXCreateGLXPixmap (display, [_manager visualInfo], _pixmap);
 #endif
 	if(!_drawable)
 		NSLog(@"Failed to make a drawable");
+	NSLog(@"Drawable %lp", _drawable);
+	XSync(display, None);
 NSLog(@"damage");
 	_damage = XDamageCreate (display, _window, XDamageReportDeltaRectangles);
 	if(!_texture)
 		glGenTextures (1, &_texture);
-NSLog(@"texture");
+	XSync(display, None);
+	return;
+NSLog(@"texture; binding %p", _drawable);
 	if(glXBindTexImageEXT)
 		glXBindTexImageEXT(display, _drawable, GLX_FRONT_EXT, NULL);
+NSLog(@"texture bound");
+	XSync(display, None);
 }
 -(void)_freeResources
 {
 }
 -(void)_collectAttributes
 {
-	NSLog(@"Collecting attributes for %ld...", _window);
+	NSLog(@"Collecting attributes for %lp...", _window);
 	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
 	Display * display = [mainDisplay display];
 	XWindowAttributes attr = { 0 };
 		case DestroyNotify:
 		if(event.xdestroywindow.window == _window)
 		{
-			NSLog(@"Managed Window %ld is destroyed", _window);
+			NSLog(@"Managed Window %lp is destroyed", _window);
 			[_manager stopManagingWindow:self];
 		}
 		break;
 		case Expose:
 		if(event.xexpose.window == _window)
 		{
-			NSLog(@"Managed Window %ld is exposed", _window);
+			NSLog(@"Managed Window %lp is exposed", _window);
 			
 		}
 		break;
 		case ConfigureNotify:
 		if(event.xconfigure.window == _window)
 		{
-			NSLog(@"Managed Window %ld is configured", _window);
+			NSLog(@"Managed Window %lp is configured", _window);
 			// TODO: recollect attributes, rebuild window management
 			[self _freeResources];
 			[self _collectAttributes];
 		if(event.xreparent.window == _window)
 		{
 			// FIXME what if window is actually moved to root?
-			NSLog(@"Managed window %ld reparented - treating as unmapped", _window);
+			NSLog(@"Managed window %lp reparented - treating as unmapped", _window);
 			if(!_isMapped)
 				break;
 			[self _freeResources];
 		case MapNotify:
 		if(event.xmap.window == _window)
 		{
-			NSLog(@"Managed Window %ld is mapped", _window);
+			NSLog(@"Managed Window %lp is mapped", _window);
 			if(_isMapped)
 				break;
 			[self _freeResources];
 		case UnmapNotify:
 		if(event.xunmap.window == _window)
 		{
-			NSLog(@"Managed Window %ld is unmapped", _window);
+			NSLog(@"Managed Window %lp is unmapped", _window);
 			if(!_isMapped)
 				break;
 			[self _freeResources];
 		case VisibilityNotify:
 		if(event.xvisibility.window == _window)
 		{
-			NSLog(@"Managed Window %ld changed visibility", _window);
+			NSLog(@"Managed Window %lp changed visibility", _window);
 			[self _freeResources];
 			[self _collectAttributes];
 			[self _buildResources];
 			if(((XDamageNotifyEvent *)&event)->drawable == _window)
 			{
 				XRectangle area = (((XDamageNotifyEvent *)&event)->area);
-				NSLog(@"Managed Window %ld damaged", _window);
+				NSLog(@"Managed Window %lp damaged", _window);
 				NSLog(@" - %hd %hd %hu %hu", area.x, area.y, area.width, area.height);
 				
 				if(_damage)
 	}
 	if(!_drawable)
 	{
-		NSLog(@"Cannot paint window %ld, no drawable", _window);
+		NSLog(@"Cannot paint window %lp, no drawable", _window);
 		return;
 	}
 
-
+	PRINT_CURRENT_CONTEXT;
 #if !SWITCH_CONTEXTS
-	glXMakeContextCurrent (display, [_manager stage], [_manager stage], [_manager glxContext]);
+	SWITCH_TO_STAGE_CONTEXT;
 #endif
 
 	[self bindTexture];
 #if SWITCH_CONTEXTS
-	glXMakeContextCurrent (display, [_manager stage], [_manager stage], [_manager glxContext]);
+	SWITCH_TO_STAGE_CONTEXT;
 #endif
 	glDrawBuffer (GL_BACK);
 
 	glColor4f(1,1,0.5+sin(_timeAlive*2)/2,1);
 	NSLog(@"%g %g", _timeAlive, 0.5+sin(_timeAlive/5)/2);
 	glBindTexture(_textureTarget, _texture);
-	
+
+	PRINT_CURRENT_CONTEXT;
+#if 0	
 	glMatrixMode(GL_MODELVIEW);
 	glPushMatrix ();
 		glTranslatef (_x, _y, _z);
 		/*
 		extent_clip (0, 0, mirror->w, mirror->h);
 		*/
+#if 0
 		glBegin(GL_QUADS);
 		/*
 		for (list = mirror->draw_zone; list; list = g_slist_next (list))
 		/*
 		extent_unclip ();
 		*/
+#endif
 
 		glLineWidth(4);		
 		glDisable(_textureTarget);
-		glColor4f(0,0,0,1);
+		glColor4f(1,0.5+sin(_timeAlive*3)/2,1,1);
 		glBegin(GL_LINE_LOOP);
 		glVertex2f(0,0);
 		glVertex2f(0,_height);
 		glColor4f(1,1,1,1);
 		glEnable(_textureTarget);
 		glLineWidth(1);
+NSLog(@"___________ WINDOW %d x %d", _width, _height);
 
 	glPopMatrix ();
+#endif
 	
 	glDisable(_textureTarget);
 	[self unbindTexture];
 
 	glXWaitGL();
 #if SWITCH_CONTEXTS
-	glXMakeContextCurrent (display, [_manager stage], [_manager stage], [_manager glxContext]);
+	SWITCH_TO_STAGE_CONTEXT;
 #endif
 }
 static int grabCount = 0;
 		NSLog(@"No drawable, skipping bind");
 		return;
 	}
-		
+	
 	glXWaitX();
 	XSync(display, None);
 	grabCount++;
 
 #if SWITCH_CONTEXTS
 	NSLog(@"Context switch");
-	glXMakeContextCurrent (display, _window, _window, [_manager glxContext]);
+	SWITCH_TO_WINDOW_CONTEXT;
 #endif
 
 
 
 	if(glXBindTexImageEXT)
 	{
-#if SWITCH_CONTEXTS
-NSLog(@"Switching context");
-		glXMakeContextCurrent (display, [_manager stage], [_manager stage], [_manager glxContext]);
-#endif
 NSLog(@"Beginning bind");
 		glEnable(_textureTarget);
 		glBindTexture(_textureTarget, _texture);
 NSLog(@"Bound texture, now binding drawable %d", _drawable);
 		glXBindTexImageEXT(display, _drawable, GLX_FRONT_EXT, NULL);
 NSLog(@"Bound drawable");
+		glDisable(_textureTarget);
 	}
 	else
 	{
+
+
 		glEnable(_textureTarget);
 		glBindTexture(_textureTarget, _texture);
 
 		glReadBuffer (GL_FRONT);
-		glDrawBuffer (GL_FRONT);
+		//glDrawBuffer (GL_FRONT);
 
 #if HAVE_GL_COPY_TEX_IMAGE_2D
 		// FIXME: we don't actually get any image for some reason
 		glCopyTexImage2D (_textureTarget, 0, GL_RGBA, 
 				0, 0, _width, _height, 0);
 #else
+		NSLog(@"Abysmally slow glReadPixels");
 		// FIXME: abysmally slow, and blurry, too
 		GLubyte * img = (GLubyte*)malloc(_width * _height * 4);
 		glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, img);	
 		gluBuild2DMipmaps(_textureTarget, GL_RGBA, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, img);
+		FILE * f = fopen("/tmp/windowshot.raw", "wb");
+		fwrite(img, _width*_height*4, 1, f);
+		fclose(f);
 		free(img);
 #endif
+
+		glDisable(_textureTarget);
 	}
-	
+SWITCH_TO_STAGE_CONTEXT;	
 NSLog(@"Bound");
 //exit(0);
 }
 {
 	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
 	Display * display = [mainDisplay display];
+	
+#if SWITCH_CONTEXTS
+	SWITCH_TO_STAGE_CONTEXT;
+#endif
 
 	if(!_drawable)
 		return;
 	if(glXReleaseTexImageEXT)
 	{
 		NSLog(@"Releasing tex image");
-#if SWITCH_CONTEXTS
-		glXMakeContextCurrent (display, [_manager stage], [_manager stage], [_manager glxContext]);
-#endif
 		glXReleaseTexImageEXT(display, _drawable, GLX_FRONT_EXT);
 	}
 
 	glBindTexture (_textureTarget, 0);
-#if SWITCH_CONTEXTS
-	glXMakeContextCurrent (display, _window, _window, [_manager glxContext]);
-#endif
 	glDisable(_textureTarget);
 
 	NSLog(@"Ungrabbing server %d", grabCount);

FPWindowManager.m

 #import "FPWindowManager.h"
 #import "FPX11Display.h"
 #import "FPManagedWindow.h"
-
-#define VBOXCOMPAT 0 // virtualbox and xephyr compatibility
-#define USE_TEXTURE_RECTANGLE 0
+#import "GLConfiguration.h"
 
 static int attrListSgl[] = {
     GLX_RGBA, GLX_RED_SIZE, 4,
     None
 };
 
+static void x11ErrorHandler(Display * dpy, XErrorEvent * errEvt)
+{
+	NSLog(@"An X error has occurred");
+}
+
 @implementation FPWindowManager
 -(id)init
 {
 	if(!self)
 		return nil;
 
-	_managedWindows = [NSMutableArray new];
+	_managedWindows = [NSMutableArray new];	
 	
 	mainDisplay = [FPX11Display mainDisplay];	
 	display = [mainDisplay display];
-	
+
+	/////////////////////
+
+	int compositeBaseEvent = 0, compositeBaseError = 0;
+	if(!XCompositeQueryExtension(display, &compositeBaseEvent, &compositeBaseError))
+	{
+		NSLog(@"Composite extension not supported!");
+		[self release];
+		return nil;
+	}
+
+	int compositeVersionMajor = 0, compositeVersionMinor = 0;
+	XCompositeQueryVersion(display, &compositeVersionMajor, &compositeVersionMinor);
+	NSLog(@"Composite extension version: %d.%d", compositeVersionMajor, compositeVersionMinor);
+
+	///////////////////
+
+	XSetErrorHandler(x11ErrorHandler);
+
+	///////////////////
 
 	[self _openStageWindow];
 
 	Display * display = [mainDisplay display];
 
 	XFree(_glxFBConfigs);
-	glXMakeCurrent(display, None, NULL);
+	[mainDisplay makeCurrentContext:NULL
+	                       onWindow:None
+	                    contextName:@"Stage"];
 	glXDestroyContext(display, _glxContext);
 	XDestroyWindow(display, _stage);
 	XCompositeReleaseOverlayWindow(display, _overlay);
 		0, 
 		NULL);
 
-	glXMakeCurrent(display, _stage, _glxContext);
+	[mainDisplay makeCurrentContext:_glxContext
+	                       onWindow:_stage
+	                    contextName:@"Stage"];
 	
 	///////////
 		
 
 -(void)render
 {
-	glXMakeContextCurrent ([[FPX11Display mainDisplay] display], _stage, _stage, _glxContext);
+	FPX11Display * mainDisplay = [FPX11Display mainDisplay];
+	Display * display = [mainDisplay display];
+	[mainDisplay makeCurrentContext:_glxContext
+	                       onWindow:_stage
+	                    contextName:@"Stage"];
+
 	XSync([[FPX11Display mainDisplay] display], False);
+	NSLog(@"=============== NEXT FRAME ===========");
+	NSLog(@"Starting with context %@", [mainDisplay glxContextName]);
 	glViewport(0, 0, _width, _height);
 	glClearColor(0.2,0.2,0.4,1);
 	glClear(GL_COLOR_BUFFER_BIT);
 
 	for(FPManagedWindow *managedWindow in _managedWindows)
 	{
+		NSLog(@"Window draw with context %@", [mainDisplay glxContextName]);
 		[managedWindow drawWindow];		
+		NSLog(@"Window drawn with context %@", [mainDisplay glxContextName]);
 	}
 
-#if 0
+#if 1
 	glLoadIdentity();
 	glDisable(GL_TEXTURE_2D);
 	glPointSize(10);
 	glEnd();
 #endif	
 
+	[mainDisplay makeCurrentContext:_glxContext
+	                       onWindow:_stage
+	                    contextName:@"Stage"];
+	XSync([[FPX11Display mainDisplay] display], False);
+	glFlush();
+	
 	if(_isVisualDoubleBuffered)
 	{
+		NSLog(@"SWAPPING BUFFERS");
 		glXSwapBuffers([[FPX11Display mainDisplay] display], _stage);
 	}
-	glFinish();	
+	glFinish();
 	glXWaitGL();
+	NSLog(@"Ending with context %@", [mainDisplay glxContextName]);
 	
 	/* vsync from KWin's scene_opengl in kdebase-3.90.1 */
 #if VSYNC
         glFlush();
         glXGetVideoSync( &sync );
         glXWaitVideoSync( 2, ( sync + 1 ) % 2, &sync );
+#else
+	usleep(1000000/60 * 2); // 30fps
 #endif
 	/* end vsync */
 }
 #import <X11/Xlib.h>
 #import <Foundation/Foundation.h>
 
+#define DEBUG_ACTIVE_CONTEXT 1
+
+#if DEBUG_ACTIVE_CONTEXT
+#import <GL/glx.h>
+#endif
+
 @interface FPX11Display : NSObject
 {
 	Display * _display;
+
+#if DEBUG_ACTIVE_CONTEXT
+	GLXContext _glxContextContext;
+	Window _glxContextWindow;
+	NSString * _glxContextName;
+#endif
 }
 +(FPX11Display*)mainDisplayWithDisplayName:(NSString*)displayName;
 +(FPX11Display*)mainDisplay;
 -(Visual*)visual;
 -(int)depth;
 -(Colormap)colormap;
+-(void)makeCurrentContext:(GLXContext)glxContext
+                 onWindow:(Window)x11Window
+              contextName:(NSString*)name;
+#if DEBUG_ACTIVE_CONTEXT
+-(NSString*)glxContextName;
+#endif
 @end
 {
 	return DefaultColormap(_display, [self screen]);
 }
+
+-(void)makeCurrentContext:(GLXContext)context
+                 onWindow:(Window)window
+              contextName:(NSString*)contextName
+{
+	glXMakeContextCurrent ([self display], window, window, context);
+#if DEBUG_ACTIVE_CONTEXT
+	_glxContextContext = context;
+	_glxContextWindow = window;
+	[_glxContextName release]; _glxContextName = [contextName copy];
+
+	NSLog(@"SWITCHED TO CONTEXT %@", _glxContextName);
+#endif
+}
+#if DEBUG_ACTIVE_CONTEXT
+-(NSString*)glxContextName
+{
+	return _glxContextName;
+}
+#endif
 @end

GLConfiguration.h

+
+/// FPWindowManager
+#define VBOXCOMPAT 0 // virtualbox and xephyr compatibility
+#define USE_TEXTURE_RECTANGLE 0
+#define VSYNC 0
+
+/// FPManagedWindow
+#define SAFE_MODE 0
+#define USE_GLX1_3 1
+#define SWITCH_CONTEXTS 1
+
+#if !SAFE_MODE
+	#define HAVE_GL_COPY_TEX_IMAGE_2D 0
+	#define FORCE_TEXTURE_2D 1
+	#define USE_GLXBINDTEXIMAGE 1
+#else
+	#define HAVE_GL_COPY_TEX_IMAGE_2D 0
+	#define FORCE_TEXTURE_2D 0
+	#define USE_GLXBINDTEXIMAGE 0
+	#undef USE_GLX1_3
+	#define USE_GLX1_3 0
+#endif
 int main(int argc, char **argv)
 {
 	NSAutoreleasePool * pool = [NSAutoreleasePool new];
+
 	FPWindowManager * t = [FPWindowManager new];
+	if(!t)
+	{
+		[pool release];
+		return 1;
+	}
+
 	[[FPEventLoop mainLoop] run];
 	[[FPEventLoop mainLoop] release];
 	[pool release];
 
-make
+if make ; then
+	echo "OK"
+else
+	exit 1
+fi
 #LIBGL_ALWAYS_INDIRECT=1 ./run-xephyr /usr/GNUstep/System/Tools/openapp ./Fireplace.app
 ./run-xephyr /usr/GNUstep/System/Tools/openapp ./Fireplace.app