Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreGLXConfig.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2004 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreGLXConfig.h"
    00026 #include "OgreException.h"
    00027 #include "OgreImage.h"
    00028 #include "OgreLogManager.h"
    00029
    00030 #include <cstdlib>
    00031 #include <iostream>
    00032
    00033 #include <string>
    00034
    00035 #include <X11/X.h>
    00036 #include <X11/Xutil.h>
    00037 #include <X11/Xlib.h>
    00038 #include <X11/keysym.h>
    00039 #include <X11/extensions/xf86vmode.h>
    00040
    00041 #include <X11/Intrinsic.h>
    00042 #include <X11/StringDefs.h>
    00043 #include <X11/Xaw/Command.h>
    00044 #include <X11/Xaw/Form.h>
    00045 #include <X11/Xaw/Box.h>
    00046 #include <X11/Shell.h>
    00047 #include <X11/Xaw/Toggle.h>
    00048 #include <X11/Xaw/MenuButton.h>
    00049 #include <X11/Xaw/SimpleMenu.h>
    00050 #include <X11/Xaw/SmeBSB.h>
    00051
    00052 #include <list>
    00053 namespace Ogre {
    00054
    00064 class GLXConfigurator {
    00065     /* GUI constants */
    00066     static const int wWidth = 400;      // Width of window
    00067     static const int wHeight = 300;     // Height of window
    00068     static const int col1x = 20;        // Starting x of column 1 (labels)
    00069     static const int col2x = 180;       // Starting x of column 2 (options)
    00070     static const int col1w = 150;       // Width of column 1 (labels)
    00071     static const int col2w = 200;       // Width of column 2 (options)
    00072     static const int ystart = 105;      // Starting y of option table rows
    00073     static const int rowh = 20;     // Height of one row in the option table
    00074     static const std::string GLXConfigurator::backdrop; // Background image, defined below
    00075
    00076 public:
    00077     GLXConfigurator();
    00078     ~GLXConfigurator();
    00079
    00080     bool CreateWindow();
    00081     void Main();
    00085     void Exit();
    00086 protected:
    00087     Display *mDisplay;
    00088     Window mWindow;
    00089     Pixmap mBackDrop;
    00090
    00091     int mWidth, mHeight;
    00092     // Xt
    00093     XtAppContext appContext;
    00094     Widget toplevel;
    00095
    00099     virtual Pixmap CreateBackdrop(Window rootWindow, int depth);
    00103     virtual bool Init();
    00107     virtual void Draw();
    00108 public:
    00109     /* Local */
    00110     bool accept;
    00111     /* Class that binds a callback to a RenderSystem */
    00112     class RendererCallbackData {
    00113     public:
    00114         RendererCallbackData(GLXConfigurator *parent, RenderSystem *renderer, Widget optionmenu):
    00115             parent(parent),
    00116             renderer(renderer),
    00117             optionmenu(optionmenu) {
    00118         }
    00119         GLXConfigurator *parent;
    00120         RenderSystem *renderer;
    00121         Widget optionmenu;
    00122     };
    00123     std::list<RendererCallbackData> mRendererCallbackData;
    00124
    00125     RenderSystem *mRenderer;
    00126     Widget box;                 // Box'o control widgets
    00127     std::list<Widget> mRenderOptionWidgets; // List of RenderSystem specific
    00128                         // widgets for visibility management (cleared when another rendersystem is selected)
    00129     /* Class that binds a callback to a certain configuration option/value */
    00130     class ConfigCallbackData {
    00131     public:
    00132         ConfigCallbackData(GLXConfigurator *parent, const std::string &optionName, const std::string &valueName, Widget optionmenu):
    00133             parent(parent),
    00134             optionName(optionName),
    00135             valueName(valueName),
    00136             optionmenu(optionmenu) {
    00137         }
    00138         GLXConfigurator *parent;
    00139         std::string optionName, valueName;
    00140         Widget optionmenu;
    00141     };
    00142     std::list<ConfigCallbackData> mConfigCallbackData;
    00143
    00144     void SetRenderSystem(RenderSystem *sys) {
    00145         mRenderer = sys;
    00146     }
    00147 private:
    00148     /* Callbacks that terminate modal dialog loop */
    00149     static void acceptHandler(Widget w, GLXConfigurator *obj, XtPointer callData) {
    00150         // Check if a renderer was selected, if not, don't accept
    00151         if(!obj->mRenderer)
    00152             return;
    00153         obj->accept = true;
    00154         obj->Exit();
    00155     }
    00156     static void cancelHandler(Widget w, GLXConfigurator *obj, XtPointer callData) {
    00157         obj->Exit();
    00158     }
    00159     /* Callbacks that set a setting */
    00160     static void renderSystemHandler(Widget w, RendererCallbackData *cdata, XtPointer callData) {
    00161         // Set selected renderer its name
    00162         XtVaSetValues(cdata->optionmenu, XtNlabel, cdata->renderer->getName().c_str(), 0, NULL);
    00163         // Notify Configurator (and Ogre)
    00164         cdata->parent->SetRenderer(cdata->renderer);
    00165     }
    00166     static void configOptionHandler(Widget w, ConfigCallbackData *cdata, XtPointer callData) {
    00167         // Set selected renderer its name
    00168         XtVaSetValues(cdata->optionmenu, XtNlabel, cdata->valueName.c_str(), 0, NULL);
    00169         // Notify Configurator (and Ogre)
    00170         cdata->parent->SetConfigOption(cdata->optionName, cdata->valueName);
    00171     }
    00172
    00173     /* Functions reacting to GUI */
    00174     void SetRenderer(RenderSystem *);
    00175     void SetConfigOption(const std::string &optionName, const std::string &valueName);
    00176 };
    00177 /*
    00178  * Backdrop image. This must be sized mWidth by mHeight, and produce a
    00179  * RGB pixel format when loaded with Image::load .
    00180  */
    00181 const std::string GLXConfigurator::backdrop = "GLX_backdrop.png";
    00182
    00183 GLXConfigurator::GLXConfigurator():
    00184     mDisplay(0), mWindow(0), mBackDrop(0),
    00185     mWidth(wWidth), mHeight(wHeight),
    00186     appContext(0), toplevel(0),
    00187
    00188     accept(false),
    00189     mRenderer(0) {
    00190 }
    00191 GLXConfigurator::~GLXConfigurator() {
    00192     if(mBackDrop)
    00193         XFreePixmap(mDisplay, mBackDrop);
    00194     if(toplevel) {
    00195         XtUnrealizeWidget(toplevel);
    00196         XtDestroyWidget(toplevel);
    00197     }
    00198     if(mDisplay) {
    00199         XCloseDisplay(mDisplay);
    00200     }
    00201 }
    00202
    00203 bool GLXConfigurator::CreateWindow() {
    00204
    00205
    00206     char *bla[] = {"Rendering Settings", "-bg", "black", "-fg", "green","-bd","darkgreen"};
    00207     int argc = sizeof(bla)/sizeof(*bla);
    00208
    00209     toplevel = XtVaOpenApplication(&appContext, "OGRE", NULL, 0, &argc, bla, NULL,sessionShellWidgetClass,
    00210         XtNwidth, mWidth,
    00211         XtNheight, mHeight,
    00212         XtNminWidth, mWidth,
    00213         XtNmaxWidth, mWidth,
    00214         XtNminHeight, mHeight,
    00215         XtNmaxHeight, mHeight,
    00216         XtNallowShellResize, False,
    00217         XtNborderWidth, 0,
    00218         XtNoverrideRedirect, True,
    00219         NULL, NULL);
    00220
    00221     /* Find out display and screen used */
    00222     mDisplay = XtDisplay(toplevel);
    00223     int screen = DefaultScreen(mDisplay);
    00224     Window rootWindow = RootWindow(mDisplay,screen);
    00225
    00226     /* Move to center of display */
    00227     int w = DisplayWidth(mDisplay, screen);
    00228     int h = DisplayHeight(mDisplay, screen);
    00229     XtVaSetValues(toplevel,
    00230             XtNx, w/2-mWidth/2,
    00231             XtNy, h/2-mHeight/2, 0, NULL);
    00232
    00233     /* Backdrop stuff */
    00234     mBackDrop = CreateBackdrop(rootWindow, DefaultDepth(mDisplay,screen));
    00235
    00236     /* Create toplevel */
    00237     box = XtVaCreateManagedWidget("box",formWidgetClass,toplevel,
    00238         XtNbackgroundPixmap, mBackDrop,
    00239         0,NULL);
    00240
    00241     /* Create renderer selection */
    00242     int cury = ystart + 0*rowh;
    00243
    00244     Widget lb1 = XtVaCreateManagedWidget("topLabel", labelWidgetClass, box, XtNlabel, "Select Renderer", XtNborderWidth, 0,
    00245         XtNwidth, col1w,    // Fixed width
    00246         XtNheight, 18,
    00247         XtNleft, XawChainLeft,
    00248         XtNtop, XawChainTop,
    00249         XtNright, XawChainLeft,
    00250         XtNbottom, XawChainTop,
    00251         XtNhorizDistance, col1x,
    00252         XtNvertDistance, cury,
    00253         XtNjustify, XtJustifyLeft,
    00254         NULL);
    00255     const char *curRenderName = " Select One "; // Name of current renderer, or hint to select one
    00256     if(mRenderer)
    00257         curRenderName = mRenderer->getName().c_str();
    00258     Widget mb1 = XtVaCreateManagedWidget("Menu", menuButtonWidgetClass, box, XtNlabel,curRenderName,
    00259         XtNresize, false,
    00260         XtNresizable, false,
    00261         XtNwidth, col2w,    // Fixed width
    00262         XtNheight, 18,
    00263         XtNleft, XawChainLeft,
    00264         XtNtop, XawChainTop,
    00265         XtNright, XawChainLeft,
    00266         XtNbottom, XawChainTop,
    00267         XtNhorizDistance, col2x,
    00268         XtNvertDistance, cury,
    00269         NULL);
    00270
    00271     Widget menu = XtVaCreatePopupShell("menu", simpleMenuWidgetClass, mb1,
    00272         0, NULL);
    00273
    00274     RenderSystemList* renderers = Root::getSingleton().getAvailableRenderers();
    00275     for (RenderSystemList::iterator pRend = renderers->begin();
    00276                     pRend != renderers->end(); pRend++) {
    00277         // Create callback data
    00278         mRendererCallbackData.push_back(RendererCallbackData(this, *pRend, mb1));
    00279
    00280         Widget entry = XtVaCreateManagedWidget("menuentry", smeBSBObjectClass, menu,
    00281             XtNlabel, (*pRend)->getName().c_str(),
    00282             0, NULL);
    00283         XtAddCallback(entry, XtNcallback, (XtCallbackProc)&GLXConfigurator::renderSystemHandler, &mRendererCallbackData.back());
    00284     }
    00285
    00286     Widget bottomPanel = XtVaCreateManagedWidget("bottomPanel", formWidgetClass, box,
    00287         XtNsensitive, True,
    00288         XtNborderWidth, 0,
    00289         XtNwidth, 150,  // Fixed width
    00290         XtNleft, XawChainLeft,
    00291         XtNtop, XawChainTop,
    00292         XtNright, XawChainLeft,
    00293         XtNbottom, XawChainTop,
    00294         XtNhorizDistance, mWidth - 160,
    00295         XtNvertDistance, mHeight - 40,
    00296         NULL);
    00297
    00298     Widget helloButton = XtVaCreateManagedWidget("cancelButton", commandWidgetClass, bottomPanel, XtNlabel," Cancel ", NULL);
    00299     XtAddCallback(helloButton, XtNcallback, (XtCallbackProc)&GLXConfigurator::cancelHandler, this);
    00300
    00301     Widget exitButton = XtVaCreateManagedWidget("acceptButton", commandWidgetClass, bottomPanel, XtNlabel," Accept ", XtNfromHoriz,helloButton, NULL);
    00302     XtAddCallback(exitButton, XtNcallback, (XtCallbackProc)&GLXConfigurator::acceptHandler, this);
    00303
    00304     XtRealizeWidget(toplevel);
    00305
    00306     if(mRenderer)
    00307         /* There was already a renderer selected; display its options */
    00308         SetRenderer(mRenderer);
    00309
    00310     return true;
    00311 }
    00312
    00313 Pixmap GLXConfigurator::CreateBackdrop(Window rootWindow, int depth) {
    00314     int bpl;
    00315     /* Find out number of bytes per pixel */
    00316     switch(depth) {
    00317     default:
    00318         LogManager::getSingleton().logMessage("GLX backdrop: Undsupported bit depth");
    00319         /* Unsupported bit depth */
    00320         return 0;
    00321     case 15:
    00322     case 16:
    00323         bpl = 2; break;
    00324     case 24:
    00325     case 32:
    00326         bpl = 4; break;
    00327     }
    00328     /* Create background pixmap */
    00329     unsigned char *data = 0; // Must be allocated with malloc
    00330
    00331     try {
    00332         Image img;
    00333         /* Load backdrop image using OGRE */
    00334         img.load(backdrop);
    00335         if(img.getWidth() != mWidth || img.getHeight() != mHeight ||
    00336             img.getFormat() != PF_R8G8B8) {
    00337             // Invalid image format or size
    00338             LogManager::getSingleton().logMessage("GLX backdrop: Invalid image "+backdrop+", format must be R8G8B8");
    00339             return 0;
    00340         }
    00341         // Convert and copy image
    00342         unsigned char *imgdata = (unsigned char*)img.getData();
    00343
    00344
    00345         data = (unsigned char*)malloc(mWidth * mHeight * bpl); // Must be allocated with malloc
    00346         int sptr = 0, dptr = 0;
    00347
    00348         switch(depth) {
    00349         case 16:
    00350             for(int y=0; y<mHeight; y++) {
    00351                 for(int x=0; x<mWidth; x++) {
    00352                     // 5/6/5
    00353                     data[dptr + 0] = (imgdata[sptr + 0] & 0xF8) |
    00354                              (imgdata[sptr + 1] >> 5);
    00355                     data[dptr + 1] = ((imgdata[sptr + 1] << 3) & 0xE0) |
    00356                              (imgdata[sptr + 2] >> 3);
    00357                     sptr += 3; dptr += 2;
    00358                 }
    00359             }
    00360             break;
    00361         case 24:
    00362         case 32:
    00363             for(int y=0; y<mHeight; y++) {
    00364                 for(int x=0; x<mWidth; x++) {
    00365                     data[dptr + 0] = 0;
    00366                     data[dptr + 1] = imgdata[sptr + 0];
    00367                     data[dptr + 2] = imgdata[sptr + 1];
    00368                     data[dptr + 3] = imgdata[sptr + 2];
    00369
    00370                     sptr += 3;dptr += 4;
    00371                 }
    00372             }
    00373             break;
    00374         }
    00375     } catch(Exception &e) {
    00376         // Could not find image; never mind
    00377         LogManager::getSingleton().logMessage("GLX backdrop image not found: Warning");
    00378         return 0;
    00379     }
    00380
    00381     GC context = XCreateGC (mDisplay, rootWindow, 0, NULL);
    00382
    00383     /* put my pixmap data into the client side X image data structure */
    00384     XImage *image = XCreateImage (mDisplay, NULL, depth, ZPixmap, 0,
    00385         (char*)data,
    00386         mWidth, mHeight, 8,
    00387         mWidth*bpl);
    00388     image->byte_order = MSBFirst;
    00389
    00390     /* tell server to start managing my pixmap */
    00391     Pixmap rv = XCreatePixmap(mDisplay, rootWindow, mWidth,
    00392         mHeight, depth);
    00393
    00394     /* copy from client to server */
    00395     XPutImage(mDisplay, rv, context, image, 0, 0, 0, 0,
    00396         mWidth, mHeight);
    00397
    00398     /* free up the client side pixmap data area */
    00399     XDestroyImage(image); // also cleans data
    00400     XFreeGC(mDisplay, context);
    00401
    00402     return rv;
    00403 }
    00404 bool GLXConfigurator::Init() {
    00405     // Init misc resources
    00406     return true;
    00407 }
    00408 void GLXConfigurator::Draw() {
    00409 }
    00410 void GLXConfigurator::Main() {
    00411     XtAppMainLoop(appContext);
    00412 }
    00413 void GLXConfigurator::Exit() {
    00414     XtAppSetExitFlag(appContext);
    00415 }
    00416
    00417 void GLXConfigurator::SetRenderer(RenderSystem *r) {
    00418     mRenderer = r;
    00419
    00420     // Destroy each widget of GUI of previously selected renderer
    00421     for(std::list<Widget>::iterator i=mRenderOptionWidgets.begin(); i!=mRenderOptionWidgets.end(); i++)
    00422         XtDestroyWidget(*i);
    00423     mRenderOptionWidgets.clear();
    00424     mConfigCallbackData.back();
    00425
    00426     // Create option GUI
    00427     int cury = ystart + 1*rowh + 10;
    00428
    00429     ConfigOptionMap options = mRenderer->getConfigOptions();
    00430     // Process each option and create an optionmenu widget for it
    00431     for (ConfigOptionMap::iterator it = options.begin();
    00432                     it != options.end(); it++) {
    00433         Widget lb1 = XtVaCreateManagedWidget("topLabel", labelWidgetClass, box, XtNlabel, it->second.name.c_str(), XtNborderWidth, 0,
    00434             XtNwidth, col1w,    // Fixed width
    00435             XtNheight, 18,
    00436             XtNleft, XawChainLeft,
    00437             XtNtop, XawChainTop,
    00438             XtNright, XawChainLeft,
    00439             XtNbottom, XawChainTop,
    00440             XtNhorizDistance, col1x,
    00441             XtNvertDistance, cury,
    00442             XtNjustify, XtJustifyLeft,
    00443             NULL);
    00444         mRenderOptionWidgets.push_back(lb1);
    00445         Widget mb1 = XtVaCreateManagedWidget("Menu", menuButtonWidgetClass, box, XtNlabel, it->second.currentValue.c_str(),
    00446             XtNresize, false,
    00447             XtNresizable, false,
    00448             XtNwidth, col2w,    // Fixed width
    00449             XtNheight, 18,
    00450             XtNleft, XawChainLeft,
    00451             XtNtop, XawChainTop,
    00452             XtNright, XawChainLeft,
    00453             XtNbottom, XawChainTop,
    00454             XtNhorizDistance, col2x,
    00455             XtNvertDistance, cury,
    00456             NULL);
    00457         mRenderOptionWidgets.push_back(mb1);
    00458
    00459         Widget menu = XtVaCreatePopupShell("menu", simpleMenuWidgetClass, mb1,
    00460             0, NULL);
    00461
    00462         // Process each choice
    00463         StringVector::iterator opt_it;
    00464         for (opt_it = it->second.possibleValues.begin();
    00465                         opt_it != it->second.possibleValues.end(); opt_it++) {
    00466             // Create callback data
    00467             mConfigCallbackData.push_back(ConfigCallbackData(this, it->second.name, *opt_it, mb1));
    00468
    00469             Widget entry = XtVaCreateManagedWidget("menuentry", smeBSBObjectClass, menu,
    00470                 XtNlabel, (*opt_it).c_str(),
    00471                 0, NULL);
    00472             XtAddCallback(entry, XtNcallback, (XtCallbackProc)&GLXConfigurator::configOptionHandler, &mConfigCallbackData.back());
    00473         }
    00474         cury += rowh;
    00475     }
    00476 }
    00477
    00478 void GLXConfigurator::SetConfigOption(const std::string &optionName, const std::string &valueName) {
    00479     if(!mRenderer)
    00480         // No renderer set -- how can this be called?
    00481         return;
    00482     mRenderer->setConfigOption(optionName, valueName);
    00483 }
    00484
    00485 bool GLXConfig::display(void) {
    00486     GLXConfigurator test;
    00487     /* Should this be called here? */
    00488     Root::getSingleton().restoreConfig();
    00489     /* Select previously selected rendersystem */
    00490     if(Root::getSingleton().getRenderSystem())
    00491         test.SetRenderSystem(Root::getSingleton().getRenderSystem());
    00492     /* Attempt to create the window */
    00493     if(!test.CreateWindow()) {
    00494         Except(Exception::ERR_INTERNAL_ERROR,
    00495                "Could not create configuration dialog",
    00496                "GLXConfig::display");
    00497     }
    00498     /* Modal loop */
    00499     test.Main();
    00500     if(!test.accept) {
    00501         /* User did not accept */
    00502         return false;
    00503     }
    00504
    00505     /* All done */
    00506     Root::getSingleton().setRenderSystem(test.mRenderer);
    00507     Root::getSingleton().saveConfig();
    00508
    00509     return true;
    00510 }
    00511
    00512 };
    00513

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:27 2004