/* * Copyright (C) 1997-2005, R3vis Corporation. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA, or visit http://www.gnu.org/copyleft/lgpl.html. * * Original Contributor: * Wes Bethel, R3vis Corporation, Marin County, California * Additional Contributor(s): * * The OpenRM project is located at http://openrm.sourceforge.net/. */ /* * $Id: rmcreatw.c,v 1.10 2005/06/08 18:33:02 wes Exp $ * Version: $Name: OpenRM-1-6-0-RC5 $ * $Revision: 1.10 $ * $Log: rmcreatw.c,v $ * Revision 1.10 2005/06/08 18:33:02 wes * Code cleanups to eliminate compiler warnings. * * Revision 1.9 2005/05/16 01:05:46 wes * Streamlining through code refactoring. * * Revision 1.8 2005/02/19 16:08:45 wes * Distro sync and consolidation. * * Revision 1.7 2005/01/23 17:11:49 wes * Copyright update to 2005. * * Revision 1.6 2004/01/17 04:07:53 wes * Updated copyright line for 2004. * * Revision 1.5 2003/10/03 19:17:47 wes * Use rmPipeSet/GetContext interface to interact with the RMpipe's * OpenGL context rather than using platform-specific interfaces. * * Revision 1.4 2003/07/23 13:32:32 wes * Win32: problems with offscreen rendering appeared with new context * initialization code sequence (1.5.0). Minor repairs needed to fix the bug. * * Revision 1.3 2003/02/02 02:07:18 wes * Updated copyright to 2003. * * Revision 1.2 2003/02/01 17:56:16 wes * Win32 code work to reflect new RMpipe initialization sequence. * * Revision 1.1.1.1 2003/01/28 02:15:23 wes * Manual rebuild of rm150 repository. * * Revision 1.8 2003/01/27 05:04:42 wes * Changes to RMpipe API and initialization sequence to unify GLX, WGL and CR * platforms w/o too much disruption to existing apps. * * Revision 1.7 2003/01/16 22:21:18 wes * Updated all source files to reflect new organization of header files: * all header files formerly located in include/rmaux, include/rmi, include/rmv * are now located in include/rm. * * Revision 1.6 2002/04/30 19:38:26 wes * Updated copyright dates. * * Revision 1.5 2001/06/03 20:53:22 wes * Added new routine to create windows under X11 to replace some older * code that seemed to have problems on some systems. * * Revision 1.4 2001/03/31 18:46:50 wes * Added inline doc for rmauxCreateOffscreenDrawable. * * Revision 1.3 2001/03/31 17:09:31 wes * v1.4.0-alpha2 checkin. * * Revision 1.2 2000/04/17 00:06:51 wes * Numerous documentation updates and code reorganization courtesy of jdb. * * Revision 1.1.1.1 2000/02/28 21:29:40 wes * OpenRM 1.2 Checkin * * Revision 1.1.1.1 2000/02/28 17:18:48 wes * Initial entry - pre-RM120 release, source base for OpenRM 1.2. * */ #include #include #include "../rm/rmprivat.h" #ifdef RM_WIN /* * ---------------------------------------------------- * @Name rmauxCreateW32Window @pstart HWND rmauxCreateW32Window (const RMpipe *useMe, HWND parent, int xpos, int ypos, int width, int height, char *wtitle, HINSTANCE hInstance, void *event_loop_fptr) @pend @astart const RMpipe *useMe - a handle to an initialized RMpipe object. HWND parent - the Win32 window handle to the parent window. NULL is OK. int xpos, ypos - integer values specifying the (x,y) pixel coordinate of the new window. int width, height - integer values specifying the pixel width and height of the new window. char *wtitle - a character string used as the title of the window. This string will appear in the title bar painted around your window by Wxx. HINSTANCE hInstance - an HINSTANCE handle. this handle is provided to your WinMain routine by Windows. void *event_loop_fptr - A function pointer, cast to a (void *), of your WndProc (event loop). @aend @dstart Creates a window suitable for rendering by OpenRM on the Win32 platform. Returns a valid window handle upon success, or NULL (zero) upon failure. Strictly speaking, the window is not yet ready for drawing upon conclusion of this routine due to how Win32 works. All Win32 developers must use an "init function" that is called once after the WM_CREATE message has been posted and processed. The Win32 version of rmauxEventLoop() should be used as a guide. @dend * ---------------------------------------------------- */ HWND rmauxCreateW32Window (RMpipe *useMe, HWND parent, int xpos, int ypos, int width, int height, char *wtitle, HINSTANCE hInstance, void *event_loop_fptr) { static char szAppName[] = "RM-OpenGL"; WNDCLASS wc; HWND hWnd; HDC hDC; HWND parentWindow; memset((void *)&wc, 0, sizeof(WNDCLASS)); wc.style = (CS_HREDRAW | CS_VREDRAW); /* class styles */ wc.lpfnWndProc = (WNDPROC)(event_loop_fptr); /* event loop function */ /* no per-class or per-window data */ wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; /* owner of this class */ wc.hIcon = NULL; /* icon name */ wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* arrow cursor */ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); /* efault color */ wc.lpszMenuName = NULL; /* menu from RC */ wc.lpszClassName = szAppName; /* regististry name */ /* register the window class */ RegisterClass(&wc); if (parent == NULL) parentWindow = NULL; else parentWindow = parent; /* * Create a main window for this application instance * give app name, window title, various flags & geometry, * specify no class menu, bind window instance and pass * in a handle to the RMpipe in use */ hWnd = CreateWindow(szAppName, wtitle, (WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS), xpos, ypos, width, height, parentWindow, NULL, hInstance, (void *)useMe); /* if window could not be created, return zero */ if (!hWnd) return(0); /* ** Set up for OpenGL rendering. Bind the rendering context to ** the same device context that the palette will be selected into. */ rmPipeSetWindow(useMe, hWnd, width, height); if (rmPipeCreateContext(useMe) == RM_WHACKED) rmWarning("Unable to create a suitable WGL context. "); return(hWnd); } /* * ---------------------------------------------------- * @Name rmauxCreateOffscreenDrawable @pstart HWND rmauxCreateOffscreenDrawable (const RMpipe *pipe, int width, int height, int depth, HINSTANCE hCurrentInst, void *eventLoopFuncPtr) @pend @astart const RMpipe *pipe - a handle to an RMpipe object (input). int width, height - integer values that specify the pixel dimensions of the new offscreen drawable. int depth - integer value that specifies the pixel depth of the new drawable. This value is used for both color planes and depth buffer. HINSTANCE hInstance - an HINSTANCE handle. this handle is provided to your WinMain routine by Windows. void *event_loop_fptr - A function pointer, cast to a (void *), of your WndProc (event loop). @aend @dstart Use this routine to create an offscreen drawable object in OpenRM. You can use this drawable just like a normal on-screen window, but the window is never mapped. On most systems, it is permissible to have the offscreen drawable be much larger than the actual dimensions of the physical display device. Upon success, this routine returns a non-zero drawable handle. Win32 notes (v1.4.0-alpha-2): it may be permissible to pass in a value of NULL for the eventLoopFuncPtr - we haven't tried that. Refer to the OpenRM demonstration program offscreen.c - we pass in rmauxWndProc as the "WndProc." However, because the window is never mapped, the WndProc is never invoked. @dend * ---------------------------------------------------- */ HWND rmauxCreateOffscreenDrawable (RMpipe *pipe, int width, int height, int depth, HINSTANCE hCurrentInst, void *eventLoopFuncPtr) { WNDCLASS wndClass; HWND hWnd; HDC hDC; HDC hDCFrontBuffer; char className[] = "OpenGL"; /* Define and register a window class */ memset((void *)&wndClass,0,sizeof(WNDCLASS)); wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = (WNDPROC)(eventLoopFuncPtr); /* event loop function */ /* wndClass.lpfnWndProc = WndProc; */ wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hCurrentInst; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = className, RegisterClass(&wndClass); hWnd = CreateWindow( className, /* Window class's name */ "OpenRM Offscreen", /* Title bar text */ WS_OVERLAPPEDWINDOW | /* The window's style */ WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, /* Position */ width, height, /* Size */ NULL, /* Parent window's handle */ NULL, /* Menu handle */ hCurrentInst, /* Instance handle */ NULL); /* No additional data */ if (hWnd != NULL) { rmPipeSetWindow(pipe, hWnd, width, height); if (pipe->createContextFunc(pipe) == RM_WHACKED) rmWarning("Unable to create a suitable WGL context. "); } return(hWnd); } #endif /* RM_WIN */ #ifdef RM_X #if 1 Window private_rmauxCreateXWindow(Display *dpy, Window parent, int x, int y, int width, int height, XVisualInfo *vinfo, RMenum managed, const char *winTitle, const char *iconTitle) { XSetWindowAttributes watt; XWindowAttributes att; Window window; unsigned long mask = CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect; int screen = DefaultScreen( dpy ); /* Query for GLX extension */ int erb, evb; if( !glXQueryExtension( dpy, &erb, &evb) ) { fprintf( stderr, "gfxInit() : Display \"%s\" has no GLX extension.\n", XDisplayName( "" ) ); XCloseDisplay( dpy ); exit(1); } XGetWindowAttributes( dpy, parent, &att ); /* Create a window, including Colormap */ watt.colormap = XCreateColormap( dpy, RootWindow( dpy, screen ), vinfo->visual, AllocNone); /* watt.background_pixel = 0; */ watt.border_pixel = 0; watt.override_redirect = False; watt.override_redirect = (managed == RM_TRUE) ? False : True; watt.event_mask = RM_AUX_XWINDOW_EVENT_MASK; /* watt.event_mask = ExposureMask | ButtonPressMask | PointerMotionMask | StructureNotifyMask; */ window = XCreateWindow( dpy, parent, x, y, width, height, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &watt ); XSetStandardProperties(dpy, window, winTitle, iconTitle, None, NULL, 0, NULL); XMapWindow(dpy, window); XMoveWindow(dpy, window, x, y); XSetWMColormapWindows( dpy, window, &window, 1 ); XSync(dpy, False); XFlush( dpy ); return window; } #endif /* * ---------------------------------------------------- * @Name rmauxCreateXWindow @pstart Window rmauxCreateXWindow (RMpipe *pipe, Window parent, int xPosition, int yPosition, int width, int height, const char *winTitle, const char *iconTitle, RMenum managed) @pend @astart RMpipe *pipe - a handle to an RMpipe (input, possibly modified). Window parent - an X11 Window handle to the parent window (NULL is OK). int xPosition, yPosition - integer values specifying the pixel location of the upper left corner of the new window. int width, height - integer values specifying the pixel width and height of the new window. const char *winTitle, *iconTitle - character strings containing the window title and icon title, respectively. The ultimate use of these strings is implementation and window-system specific. RMenum managed - an RMenum value indicating whether or not this window will be managed by the window manager. When not managed, the window will be drawn with no decorations, title bars, etc. and all window events will bypass the window manager and go directly to the window. RM_TRUE or RM_FALSE. Unmanaged windows are useful in VR applications. @aend @dstart This routine creates an X11 window suitable for use by OpenRM for drawing, and returns a handle to the caller. Prior to calling this routine, the RMpipe must be initialized (see rmInitPipe). Returns zero upon failure, or a Window handle upon success. During processing, this routine will check the input RMpipe for the presence of an OpenGL context and an XVisual. If both are not present, a suitable OpenGL context will be created, along with an appropriate XVisual structure. The XVisual structure is needed to ensure the new window that is created will be suitable for OpenGL rendering use. See also XCreateWindow (X11R6). @dend * ---------------------------------------------------- */ Window rmauxCreateXWindow (RMpipe *pipe, Window parent, int x, int y, int width, int height, const char *win_title, const char *icon_title, RMenum managed) { Window win; if (rmxPipeGetDisplay(pipe) == NULL) { rmError("rmauxCreateXWindow error: before calling this routine, you must first assign an XDisplay to the RMpipe using rmxPipeSetDisplay."); return 0; } if (parent == 0) parent = RootWindow(rmxPipeGetDisplay(pipe), DefaultScreen(rmxPipeGetDisplay(pipe))); /* * if either the context or the visual are null, create a new * openGL context. */ if ((rmPipeGetContext(pipe) == (GLXContext)0) || (rmxPipeGetVisual(pipe) == NULL)) { if (rmPipeCreateContext(pipe) == RM_WHACKED) { rmError("rmauxCreateXWindow fails."); return RM_WHACKED; } } /* * else, use the existing OpenGL context & visual. If the app has * made a mistake and assigned an invalid XVisual, the create window * call will fail, causing confusion. */ win = private_rmauxCreateXWindow(rmxPipeGetDisplay(pipe), parent, x, y, width, height, rmxPipeGetVisual(pipe), managed, win_title, icon_title); return(win); } /* * ---------------------------------------------------- * @Name rmauxCreateOffscreenDrawable @pstart GLXPixmap rmauxCreateOffscreenDrawable (const RMpipe *pipe, int width, int height, int depth) @pend @astart const RMpipe *pipe - a handle to an RMpipe object (input). int width, height - integer values that specify the pixel dimensions of the new offscreen drawable. int depth - integer value that specifies the pixel depth of the new drawable. This value is used for both color planes and depth buffer. @aend @dstart Use this routine to create an offscreen drawable object in OpenRM. You can use this drawable just like a normal on-screen window, but the window is never mapped. On most systems, it is permissible to have the offscreen drawable be much larger than the actual dimensions of the physical display device. Upon success, this routine returns a non-zero drawable handle. @dend * ---------------------------------------------------- */ GLXPixmap rmauxCreateOffscreenDrawable (RMpipe *pipe, int width, int height, int depth) { Pixmap p; GLXPixmap glxp; Display *d = rmxPipeGetDisplay(pipe); XVisualInfo *visual; /* * if either the context or the visual are null, create a new * openGL context. */ if ((rmPipeGetContext(pipe) == (GLXContext)0) || (rmxPipeGetVisual(pipe) == NULL)) { if (rmPipeCreateContext(pipe) == RM_WHACKED) { rmError("rmauxCreateXWindow fails."); return RM_WHACKED; } } visual = rmxPipeGetVisual(pipe); p = XCreatePixmap(d, RootWindow(d, visual->screen), width, height, visual->depth); glxp = glXCreateGLXPixmap(d, visual, p); /* foil compiler warning */ depth = 0; return(glxp); } #endif /* RM_X */ /* EOF */