toglet.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 1999-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Mon Jan  4 08:00:00 1999
00010 // commit: $Id: toglet.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/tcl-gfx/toglet.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_GFX_TOGLET_CC_UTC20050626084024_DEFINED
00035 #define GROOVX_GFX_TOGLET_CC_UTC20050626084024_DEFINED
00036 
00037 #include "toglet.h"
00038 
00039 #include "gfx/glcanvas.h"
00040 #include "gfx/glwindowinterface.h"
00041 #include "gfx/glxopts.h"
00042 #include "gfx/gxfactory.h"
00043 #include "gfx/gxscene.h"
00044 #include "gfx/rgbacolor.h"
00045 
00046 #if defined (GVX_GL_PLATFORM_GLX)
00047 #  include "gfx/glxwrapper.h"
00048 #elif defined(GVX_GL_PLATFORM_AGL)
00049 #  include "gfx/aglwrapper.h"
00050 #endif
00051 
00052 #include "nub/ref.h"
00053 
00054 #include "tcl/eventloop.h"
00055 #include "tcl/timerscheduler.h"
00056 
00057 #include "rutz/fstring.h"
00058 #include "rutz/sfmt.h"
00059 
00060 #include <limits>
00061 #include <tk.h>
00062 
00063 #ifdef GVX_GL_PLATFORM_AGL
00064 #  define HAVE_LIMITS_H
00065 #  include <tkMacOSX.h>
00066 #endif
00067 
00068 #include "rutz/trace.h"
00069 #include "rutz/debug.h"
00070 GVX_DBG_REGISTER
00071 
00072 using rutz::shared_ptr;
00073 
00074 namespace
00075 {
00076   nub::soft_ref<Toglet> theCurrentToglet;
00077 
00078   const int DEFAULT_SIZE_X = 400;
00079   const int DEFAULT_SIZE_Y = 400;
00080 }
00081 
00083 //
00084 // Toglet::Impl class definition
00085 //
00087 
00088 class Toglet::Impl
00089 {
00090 private:
00091   Impl(const Impl&);
00092   Impl& operator=(const Impl&);
00093 
00094 public:
00095 
00096   Toglet*                       const owner;
00097   Tk_Window                     const tkWin;
00098   shared_ptr<GlxOpts>           const opts;
00099 #if defined(GVX_GL_PLATFORM_GLX)
00100   shared_ptr<GlxWrapper>        const glx;
00101 #elif defined(GVX_GL_PLATFORM_AGL)
00102   shared_ptr<AglWrapper>        const glx;
00103 #endif
00104   nub::soft_ref<GLCanvas>       const canvas;
00105   GxScene*                      const scene;
00106 
00107   Impl(Toglet* p);
00108   ~Impl() throw()
00109   {
00110     if (scene != 0)       scene->destroy();
00111     if (canvas.is_valid()) canvas->destroy();
00112   }
00113 };
00114 
00115 
00116 //---------------------------------------------------------------------
00117 //
00118 // Toglet::Impl::Impl
00119 //
00120 //---------------------------------------------------------------------
00121 
00122 Toglet::Impl::Impl(Toglet* p) :
00123   owner(p),
00124   tkWin(owner->tkWin()),
00125   opts(new GlxOpts),
00126 #if defined(GVX_GL_PLATFORM_GLX)
00127   glx(GlxWrapper::make(Tk_Display(tkWin), *opts,
00128                        (GlxWrapper*)0 /*shared context*/)),
00129 #elif defined(GVX_GL_PLATFORM_AGL)
00130   glx(AglWrapper::make(*opts)),
00131 #endif
00132   canvas(GLCanvas::make(opts, glx)),
00133   scene(new GxScene(canvas, rutz::make_shared(new tcl::timer_scheduler)))
00134 {
00135 GVX_TRACE("Toglet::Impl::Impl");
00136 }
00137 
00139 //
00140 // Toglet member function definitions
00141 //
00143 
00144 namespace
00145 {
00146   // the main window can be specified with either PARENT = "" or "."
00147   rutz::fstring PARENT = "";
00148 
00149 #ifdef GVX_GL_PLATFORM_GLX
00150   void configureGlxWindow(Tk_Window tkWin, const GlxWrapper* glx)
00151   {
00152     Display* dpy = Tk_Display(tkWin);
00153 
00154     Visual* visual = glx->visInfo()->visual;
00155     const int screen = glx->visInfo()->screen;
00156 
00157     Colormap cmap =
00158       visual == DefaultVisual(dpy, screen)
00159       ? DefaultColormap(dpy, screen)
00160       : XCreateColormap(dpy,
00161                         RootWindow(dpy, screen),
00162                         visual, AllocNone);
00163 
00164     // Make sure Tk knows to switch to the new colormap when the cursor is over
00165     // this window when running in color index mode.
00166     Tk_SetWindowVisual(tkWin, visual, glx->visInfo()->depth, cmap);
00167 
00168     XSetWindowAttributes atts;
00169 
00170     atts.colormap = cmap;
00171     atts.border_pixel = 0;
00172     atts.event_mask =
00173       KeyPressMask|KeyReleaseMask|
00174       ButtonPressMask|ButtonReleaseMask|
00175       EnterWindowMask|LeaveWindowMask|
00176       PointerMotionMask|ExposureMask|
00177       VisibilityChangeMask|FocusChangeMask|
00178       PropertyChangeMask|ColormapChangeMask;
00179 
00180     unsigned long valuemask = CWBorderPixel | CWColormap | CWEventMask;
00181 
00182     if (Tk_IsTopLevel(tkWin))
00183       {
00184         atts.override_redirect = true;
00185         valuemask |= CWOverrideRedirect;
00186       }
00187 
00188     Tk_ChangeWindowAttributes(tkWin, valuemask, &atts);
00189   }
00190 #endif
00191 }
00192 
00194 //
00195 // Toglet member definitions
00196 //
00198 
00199 Toglet::Toglet(bool pack, bool topLevel) :
00200   tcl::TkWidget(tcl::event_loop::interp(), "Toglet",
00201                 rutz::sfmt("%s.togl_private%lu",
00202                            PARENT.c_str(), id()).c_str(),
00203                 topLevel),
00204   rep(new Impl(this))
00205 {
00206 GVX_TRACE("Toglet::Toglet");
00207 
00208   dbg_eval_nl(3, this);
00209 
00210   // Get the window mapped onscreen. NOTE -- we need to make these
00211   // calls here, rather than in Impl's constructor. Why? Because some
00212   // of these calls (e.g. Tk_MapWindow()) may trigger window-system
00213   // callbacks (such as ConfigureNotify), which will end up calling
00214   // Toglet's own functions, e.g. reshapeCallback(). Those functions
00215   // require that "rep" be initialized. If we do this window set up in
00216   // Impl's constructor, then it won't have returned yet, and so our
00217   // "rep" variable won't be pointing anywhere meaningful (will be
00218   // either NULL or garbage).
00219 
00220   Tk_GeometryRequest(rep->tkWin, DEFAULT_SIZE_X, DEFAULT_SIZE_Y);
00221 
00222 #ifdef GVX_GL_PLATFORM_GLX
00223   configureGlxWindow(rep->tkWin, rep->glx.get());
00224 #endif
00225 
00226   Tk_MakeWindowExist(rep->tkWin);
00227   Tk_MapWindow(rep->tkWin);
00228 
00229 #if defined(GVX_GL_PLATFORM_GLX)
00230   rep->glx->bindWindow(Tk_WindowId(rep->tkWin));
00231 #elif defined(GVX_GL_PLATFORM_AGL)
00232   rep->glx->bindDrawable(TkMacOSXGetDrawablePort(Tk_WindowId(rep->tkWin)));
00233 #endif
00234 
00235   // Bind the context to the window and make it the current context
00236   this->makeCurrent();
00237 
00238   if (rep->canvas->isRgba())
00239     {
00240       GVX_TRACE("GlxWrapper::GlxWrapper::rgbaFlag");
00241       rep->canvas->setColor(Gfx::RgbaColor(0.0, 0.0, 0.0, 1.0));
00242       rep->canvas->setClearColor(Gfx::RgbaColor(1.0, 1.0, 1.0, 1.0));
00243     }
00244   else
00245     {
00246       // FIXME use XBlackPixel(), XWhitePixel() here?
00247       rep->canvas->setColorIndex(0);
00248       rep->canvas->setClearColorIndex(1);
00249     }
00250 
00251   if (pack) tcl::TkWidget::pack();
00252 }
00253 
00254 Toglet::~Toglet() throw()
00255 {
00256 GVX_TRACE("Toglet::~Toglet");
00257 
00258   dbg_eval_nl(3, this);
00259 
00260   delete rep;
00261 }
00262 
00263 Toglet* Toglet::make()
00264 {
00265 GVX_TRACE("Toglet::make");
00266 
00267   Toglet* p = new Toglet;
00268 
00269   return p;
00270 }
00271 
00272 Toglet* Toglet::makeToplevel()
00273 {
00274 GVX_TRACE("Toglet::makeToplevel");
00275   Toglet* p = new Toglet(true, true);
00276 
00277   return p;
00278 }
00279 
00280 nub::soft_ref<Toglet> Toglet::getCurrent()
00281 {
00282 GVX_TRACE("Toglet::getCurrent");
00283   return theCurrentToglet;
00284 }
00285 
00286 void Toglet::setCurrent(nub::soft_ref<Toglet> toglet)
00287 {
00288 GVX_TRACE("Toglet::setCurrent");
00289   dbg_eval(1, toglet.id());
00290   toglet->makeCurrent();
00291 }
00292 
00293 void Toglet::defaultParent(const char* pathname)
00294 {
00295 GVX_TRACE("Toglet::defaultParent");
00296   PARENT = pathname;
00297 }
00298 
00299 nub::soft_ref<Gfx::Canvas> Toglet::getCanvas() const
00300 {
00301 GVX_TRACE("Toglet::getCanvas");
00302   makeCurrent();
00303   return rep->canvas;
00304 }
00305 
00306 void Toglet::makeCurrent() const
00307 {
00308   if (theCurrentToglet.id() != this->id() ||
00309       GLCanvas::getCurrent().id() != rep->canvas->id())
00310     {
00311       rep->canvas->makeCurrent();
00312       theCurrentToglet = nub::soft_ref<Toglet>(const_cast<Toglet*>(this));
00313     }
00314 }
00315 
00316 void Toglet::displayCallback()
00317 {
00318 GVX_TRACE("Toglet::displayCallback");
00319   fullRender();
00320 }
00321 
00322 void Toglet::reshapeCallback(int width, int height)
00323 {
00324 GVX_TRACE("Toglet::reshapeCallback");
00325 
00326   GVX_ASSERT(rep->glx.get() != 0);
00327   GVX_ASSERT(rep->scene != 0);
00328 
00329   makeCurrent();
00330   rep->glx->onReshape(width, height);
00331   rep->scene->reshape(width, height);
00332 }
00333 
00334 void Toglet::swapBuffers()
00335 {
00336 GVX_TRACE("Toglet::swapBuffers");
00337   makeCurrent();
00338   rep->canvas->flushOutput();
00339 }
00340 
00341 GxScene& Toglet::scene()
00342 {
00343 GVX_TRACE("Toglet::scene");
00344   return *(rep->scene);
00345 }
00346 
00347 void Toglet::render()
00348 {
00349   makeCurrent();
00350   rep->scene->render();
00351 }
00352 
00353 void Toglet::fullRender()
00354 {
00355   makeCurrent();
00356   rep->scene->fullRender();
00357 }
00358 
00359 void Toglet::clearscreen()
00360 {
00361   makeCurrent();
00362   rep->scene->clearscreen();
00363 }
00364 
00365 void Toglet::fullClearscreen()
00366 {
00367   makeCurrent();
00368   rep->scene->fullClearscreen();
00369 }
00370 
00371 void Toglet::undraw()
00372 {
00373   makeCurrent();
00374   rep->scene->undraw();
00375 }
00376 
00377 void Toglet::setVisibility(bool vis)
00378 {
00379   makeCurrent();
00380   rep->scene->setVisibility(vis);
00381 }
00382 
00383 void Toglet::setHold(bool hold_on)
00384 {
00385   makeCurrent();
00386   rep->scene->setHold(hold_on);
00387 }
00388 
00389 void Toglet::allowRefresh(bool allow)
00390 {
00391   makeCurrent();
00392   rep->scene->allowRefresh(allow);
00393 }
00394 
00395 const nub::ref<GxCamera>& Toglet::getCamera() const
00396 {
00397   makeCurrent();
00398   return rep->scene->getCamera();
00399 }
00400 
00401 void Toglet::setCamera(const nub::ref<GxCamera>& cam)
00402 {
00403   makeCurrent();
00404   rep->scene->setCamera(cam);
00405 }
00406 
00407 void Toglet::setDrawable(const nub::ref<GxNode>& node)
00408 {
00409   makeCurrent();
00410   rep->scene->setDrawable(node);
00411 }
00412 
00413 void Toglet::animate(unsigned int framesPerSecond)
00414 {
00415   makeCurrent();
00416   rep->scene->animate(framesPerSecond);
00417 }
00418 
00419 static const char __attribute__((used)) vcid_groovx_gfx_toglet_cc_utc20050626084024[] = "$Id: toglet.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00420 #endif // !GROOVX_GFX_TOGLET_CC_UTC20050626084024_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:41 2008 by Doxygen version 1.5.5.