AGL problems and fixes

If you've had any problems with Nexuiz, or would like to report bugs, post here.

Moderators: Nexuiz Moderators, Moderators

AGL problems and fixes

Postby ds01 » Wed Apr 12, 2006 3:52 pm

Attention maintainers: there are two bugs in current cvs file vid_agl.c
and there are fixes for them both.

The first bug is the holding a mouse button blocks mouse movement, because kEventMouseMoved and kEventMouseDragged are mutual exclusives while monitoring kEventMouseDown/Up in same routine. The fix for that is to just remove the break from kEventMouseDragged and place the case in the same switch as kEventMouseMoved.

The second bug is FullScreen is broken, because the deprecated function call to get the main display was removed - using aglSetFullScreen requires the device be specified in qaglChoosePixelFormat. Also [in qaglChoosePixelFormat] when using NULL you need to use 0 [verified in the docs], and using NULL with 1 won't work when wanting FullScreen. There is actually a workaround for this that uses non-deprecated methods (also shown in code below).

(The added aglGetError parts I just left in this block, of course you could just revert to the style of error checks it used before.) I made an effort to comment it well enough, so here's the patch:
Code: Select all
--- vid_agl.c.orig   2006-03-28 08:02:06.000000000 -0500
+++ vid_agl.c   2006-04-12 10:38:39.000000000 -0400
@@ -334,7 +334,7 @@
   }
}

-static void VID_BuildAGLAttrib(GLint *attrib, int stencil, qboolean fullscreen)
+static void VID_BuildAGLAttrib(GLint *attrib, GLint stencil, qboolean fullscreen)
{
   *attrib++ = AGL_RGBA;
   *attrib++ = AGL_RED_SIZE;*attrib++ = 1;
@@ -366,6 +366,11 @@
   Rect windowBounds;
   AGLPixelFormat pixelFormat;
   GLint attributes [32];
+   GLenum error;
+
+   // FullScreen Display stuff
+   GDHandle gdhDisplay; // = GetMainDevice(); /*deprecated*/
+   CGDirectDisplayID mainDisplay = CGMainDisplayID();

   if (!GL_OpenLibrary())
   {
@@ -415,35 +420,106 @@
   InstallWindowEventHandler (window, NewEventHandlerUPP (MainWindowEventHandler),
                        GetEventTypeCount(winEvents), winEvents, window, NULL);

-   // Create and set pixel format
+   // Create the desired attribute list
   VID_BuildAGLAttrib(attributes, bpp == 32, fullscreen);
-   pixelFormat = qaglChoosePixelFormat(NULL, 1, attributes);
-   if (pixelFormat == NULL)
+
+   if (!fullscreen)
   {
-      Con_Printf("Unable to create pixel format\n");
-      ReleaseWindow(window);
-      return false;
+   //  Output to Window
+   //  Set pixel format with built attribs
+   //  Note: use NULL then must use 0
+   pixelFormat = qaglChoosePixelFormat(NULL, 0, attributes);
+   error = aglGetError();
+      if (error != AGL_NO_ERROR)
+         {
+            Con_Printf("qaglChoosePixelFormat FAILED: %s\n",
+                    (char *)aglErrorString(error));
+            ReleaseWindow(window);
+            return false;
+         }
   }

-   // Set context and show the window
-   context = qaglCreateContext(pixelFormat, NULL);
-   if (context == NULL)
-      Sys_Error ("aglCreateContext failed");
   if (fullscreen)
   {
-      if (!qaglSetFullScreen (context, width, height, refreshrate, 0))
-         Sys_Error("aglSetFullScreen failed");
-      vid_isfullscreen = true;
+      //  Output is FullScreen
+      //  Get the mainDisplay and set resolution to current
+      CGDisplayCapture (mainDisplay);
+      CFDictionaryRef refDisplayMode = CGDisplayBestModeForParameters (mainDisplay, bpp, width, height, NULL);
+      CGDisplaySwitchToMode (mainDisplay, refDisplayMode);
+      DMGetGDeviceByDisplayID ((DisplayIDType)mainDisplay, &gdhDisplay, false);
+
+      //  Set pixel format with built attribs
+      //  Note: specifying a device is *required* for AGL_FullScreen
+      pixelFormat = qaglChoosePixelFormat(&gdhDisplay, 1, attributes);
+      error = aglGetError();
+      if (error != AGL_NO_ERROR)
+      {
+         Con_Printf("qaglChoosePixelFormat FAILED: %s\n",
+                 (char *)aglErrorString(error));
+         ReleaseWindow(window);
+         return false;
+      }
   }
-   else
+
+   // Create a context using the pform
+   context = qaglCreateContext(pixelFormat, NULL);
+   error = aglGetError();
+   if (error != AGL_NO_ERROR)
   {
-      if (!qaglSetDrawable(context, GetWindowPort(window)))
-         Sys_Error ("aglSetDrawable failed");
+      Con_Printf("qaglCreateContext FAILED: %s\n",
+              (char *)aglErrorString(error));
   }
-   if (!qaglSetCurrentContext(context))
-      Sys_Error ("aglSetCurrentContext failed");
+
+   // Make the context the current one ('enable' it)
+   qaglSetCurrentContext(context);   
+   error = aglGetError();
+      if (error != AGL_NO_ERROR)
+      {
+         Con_Printf("qaglSetCurrentContext FAILED: %s\n",
+                 (char *)aglErrorString(error));
+         ReleaseWindow(window);
+         return false;
+      }
+
+   // Discard pform
   qaglDestroyPixelFormat(pixelFormat);

+   // Attempt fullscreen if requested
+   if (fullscreen)
+   {
+      qaglSetFullScreen (context, width, height, refreshrate, 0);
+      error = aglGetError();
+      if (error != AGL_NO_ERROR)
+      {
+         Con_Printf("qaglSetFullScreen FAILED: %s\n",
+                 (char *)aglErrorString(error));
+         return false;
+         // FullScreen Failed
+         vid_isfullscreen = false;
+      }
+      else
+      {
+         // FullScreen Success
+         vid_isfullscreen = true;
+      }
+   }
+   
+   if (!fullscreen)
+   {
+   // Note: this _is_ a Window != FullScreen
+   // Set Window as Drawable
+   qaglSetDrawable(context, GetWindowPort(window));
+   error = aglGetError();
+      if (error != AGL_NO_ERROR)
+      {
+         Con_Printf("qaglSetDrawable FAILED: %s\n",
+                 (char *)aglErrorString(error));
+         ReleaseWindow(window);
+         return false;
+      }
+
+   }
+
   scr_width = width;
   scr_height = height;

@@ -619,7 +695,10 @@
                  Key_Event(key, '\0', eventKind == kEventMouseDown);
                  break;

+               // Note: These two events are mutual exclusives
+               // Treat MouseDragged in the same statement, so we don't block MouseMoved while a mousebutton is held
               case kEventMouseMoved:
+               case kEventMouseDragged:
               {
                  HIPoint deltaPos;

@@ -643,9 +722,6 @@
                  break;
               }

-               case kEventMouseDragged:
-                  break;
-
               default:
                  Con_Printf (">> kEventClassMouse (UNKNOWN eventKind: %d) <<\n", eventKind);
                  break;

ds01
Member
 
Posts: 47
Joined: Wed Mar 29, 2006 5:54 am
Location: Lvl 7

Postby ds01 » Wed Apr 12, 2006 9:39 pm

Forgot to say the mouse is much smoother/faster in AGL than in the SDL version. The graphics also seem much improved and even faster, although it may just be perceived from the improved input :D
ds01
Member
 
Posts: 47
Joined: Wed Mar 29, 2006 5:54 am
Location: Lvl 7

Re: AGL problems and fixes

Postby Mathieu Olivier » Thu Apr 13, 2006 6:34 am

ds01 wrote:The second bug is FullScreen is broken, because the deprecated function call to get the main display was removed - using aglSetFullScreen requires the device be specified in qaglChoosePixelFormat. Also [in qaglChoosePixelFormat] when using NULL you need to use 0 [verified in the docs], and using NULL with 1 won't work when wanting FullScreen. There is actually a workaround for this that uses non-deprecated methods (also shown in code below).

What do you mean by "is broken" exactly? The current code works on my iBook + Mac OS X 10.4 or I wouldn't have commited it :P Do you have a dual screen or something like that?
Anyhow, I have saved your patch on my HD and will look at it more carefully this week-end. The fix for the mouse bug will certainly be merged in the current CVS code, but I would like to take some time to fully understand your changes in the AGL initialization part before merging the rest of the patch.

Anyway, thanks for your contribution. This piece of code is my first OSX code ever, so I'm certainly not yet at ease with this platform. :)
Mathieu Olivier
Newbie
 
Posts: 3
Joined: Thu Apr 13, 2006 6:25 am

Re: AGL problems and fixes

Postby ds01 » Fri Apr 14, 2006 3:43 am

Mathieu Olivier wrote:What do you mean by "is broken" exactly? The current code works on my iBook + Mac OS X 10.4 or I wouldn't have commited it :P Do you have a dual screen or something like that?


I was actually wondering if perhaps you had multiple screens, and that's why it worked for you lol

What I mean precisely is it just crashes trying to go FullScreen, and works only if going to Window mode. The exact reason why this fails is because the context for aglSetFullScreen is invalid. The reason why the context is invalid is because the parameters for aglChoosePixelFormat are invalid when applied to aglSetFullScreen (the Context is created using the PixelFormat).

Being even more specific using aglChoosePixelFormat set to 'NULL, 1, attributes' is not right, quoting the API doc:
gdevs - To evaluate all devices, pass NULL.
ndev - Pass 0 if you also pass NULL for the gdevs parameter.

It should use 'NULL, 0, attributes' for window mode, and it is also well-complained about on message boards and mailing lists about _having_ to specify the handle for a specific video device in order for aglSetFullScreen to even work.

I have verified both of these, but only after implementing all of those aglGetError checks. This is what happens under the following cases:

1A) aglChoosePixelFormat(NULL, 1, attributes);
1A = results with invalid video device error

2B) aglChoosePixelFormat(NULL, 0, attributes);
2B + aglSetFullScreen = invalid context error

3C) aglChoosePixelFormat(&gdhDisplay, 1, attributes);
3C + aglSetFullScreen = Success

These errors were confirmed along the pipeline through their specific functions. They are working as expected, and I don't know why a] it's not clearly stated in the API the mandantory device specification for aglSetFullScreen, or b] why it seemingly worked on your iBook.

I realize that some things are not commented very well in that patch and will do that now for you :)

Code: Select all
/* ---Window Manager, in Carbon--- */
//This am pretty sure you know already :)
GDHandle gdhDisplay;

/* ---These here are all Quartz--- */
//CGMainDisplayID returns the display ID of the main display
CGDirectDisplayID mainDisplay = CGMainDisplayID();
//  Captures display for exclusive use
CGDisplayCapture (mainDisplay);
//  Finds the closest display mode to the desired specifications
CFDictionaryRef refDisplayMode = CGDisplayBestModeForParameters (mainDisplay, bpp, width, height, NULL);
//  Switches display to the mode obtained in previous function
CGDisplaySwitchToMode (mainDisplay, refDisplayMode);

/* ---This here is Display Manager, from Carbon--- */
//  Obtains a handle for the video device with the specified display ID
DMGetGDeviceByDisplayID ((DisplayIDType)mainDisplay, &gdhDisplay, false);



Technically three of those Quartz calls are more like preparatory, (capture, search closest, switch to nearest found), and aren't required on my machine. They may be desired on other machines (some people do those always), and my thinking behind those three being you maybe had multi-head displays.

Just trying to help and be informative, while hoping to not come off sounding ill-mannered so forgive me if I do :shock:

Mathieu Olivier wrote:Anyway, thanks for your contribution. This piece of code is my first OSX code ever, so I'm certainly not yet at ease with this platform. :)


These are just small things and really I should be thanking you so ThankS for taking the time to write the AGL you did a great job! It was really bugging me not being able to use it, especially since X11 has the GLX version and Win32 users the WGL. Choice is good hehe ;)
ds01
Member
 
Posts: 47
Joined: Wed Mar 29, 2006 5:54 am
Location: Lvl 7

Re: AGL problems and fixes

Postby Mathieu Olivier » Fri Apr 14, 2006 5:42 am

ds01 wrote:I was actually wondering if perhaps you had multiple screens, and that's why it worked for you lol

:D
ds01 wrote:...
These errors were confirmed along the pipeline through their specific functions. They are working as expected, and I don't know why a] it's not clearly stated in the API the mandantory device specification for aglSetFullScreen, or b] why it seemingly worked on your iBook.

I will double check that this week-end. I may have broken something in my latest commit.
Anway, LordHavoc has been faster than me, and your patch has already been merged 8) There's a few minor things I still need to change (aglGetError() and another function aren't dynamically linked like the other functions), but as far as I can tell it works great for me / my iBook.

ds01 wrote:These are just small things and really I should be thanking you so ThankS for taking the time to write the AGL you did a great job! It was really bugging me not being able to use it, especially since X11 has the GLX version and Win32 users the WGL. Choice is good hehe ;)

Thanks :) As you say, choice is good. ;) And also I wouldn't like the fact that DP would require Mac people to have SDL in order to play.
Mathieu Olivier
Newbie
 
Posts: 3
Joined: Thu Apr 13, 2006 6:25 am

Postby ds01 » Tue Apr 18, 2006 10:33 pm

Hey I forgot to ask you- is your iBook a G4 model with the Radeon 9550, and if it is then does GLSL work for you?

Thanks again for your time :)
ds01
Member
 
Posts: 47
Joined: Wed Mar 29, 2006 5:54 am
Location: Lvl 7


Return to Nexuiz - Support / Bugs

Who is online

Users browsing this forum: No registered users and 1 guest

cron