Shadowrun: Awakened 29 September 2011 - Build 871
macvideo.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2010 Intel Corporation.  All Rights Reserved.
00003 
00004     This file is part of Threading Building Blocks.
00005 
00006     Threading Building Blocks is free software; you can redistribute it
00007     and/or modify it under the terms of the GNU General Public License
00008     version 2 as published by the Free Software Foundation.
00009 
00010     Threading Building Blocks is distributed in the hope that it will be
00011     useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00012     of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with Threading Building Blocks; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019     As a special exception, you may use this file as part of a free software
00020     library without restriction.  Specifically, if other files instantiate
00021     templates or use macros or inline functions from this file, or you compile
00022     this file and link it with other files to produce an executable, this
00023     file does not by itself cause the resulting executable to be covered by
00024     the GNU General Public License.  This exception does not however
00025     invalidate any other reasons why the executable file might be covered by
00026     the GNU General Public License.
00027 */
00028 
00029 /*
00030  *  Based on "OpenGL Image" example from http://developer.apple.com/samplecode/OpenGL_Image/
00031  */
00032 
00033 #include "video.h"
00034 #include <sched.h>
00035 #include <sys/time.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038 #include <pthread.h>
00039 
00040 #include <AvailabilityMacros.h>
00041 #undef DEPRECATED_ATTRIBUTE
00042 #define DEPRECATED_ATTRIBUTE
00043 #include <Carbon/Carbon.h>
00044 #include <AGL/agl.h>
00045 #include <OpenGL/gl.h>    // for OpenGL API
00046 #include <OpenGL/glext.h> // for OpenGL extension support 
00047 
00048 unsigned int *      g_pImg = 0;
00049 int                 g_sizex, g_sizey;
00050 WindowRef           g_window = 0;
00051 static video *      g_video = 0;
00052 static int          g_fps = 0;
00053 struct timeval      g_time;
00054 static pthread_mutex_t  g_mutex = PTHREAD_MUTEX_INITIALIZER;
00055 
00056 
00057 static OSStatus     AppEventHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon );
00058 WindowRef           HandleNew();
00059 static OSStatus     WindowEventHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon );
00060 
00061 static IBNibRef     sNibRef;
00062 
00063 //-------------------------------------------------------------------------------------------- 
00064 
00065 // structure for creating a fullscreen context
00066 struct structGLInfo // storage for setup info
00067 {
00068     SInt16 width;               // input: width of drawable (screen width in full screen mode), return: actual width allocated
00069     SInt16 height;              // input: height of drawable (screen height in full screen mode), return: actual height allocated
00070     UInt32 pixelDepth;          // input: requested pixel depth
00071     Boolean fDepthMust;         // input: pixel depth must be set (if false then current depth will be used if able)
00072     Boolean fAcceleratedMust;   // input: must renderer be accelerated?
00073     GLint aglAttributes[64];    // input: pixel format attributes always required (reset to what was actually allocated)
00074     SInt32 VRAM;                // input: minimum VRAM; output: actual (if successful otherwise input)
00075     SInt32 textureRAM;          // input: amount of texture RAM required on card; output: same (used in allcoation to ensure enough texture
00076     AGLPixelFormat    fmt;      // input: none; output pixel format...
00077 };
00078 typedef struct structGLInfo structGLInfo;
00079 typedef struct structGLInfo * pstructGLInfo;
00080 
00081 // structure for creating a context from a window
00082 struct structGLWindowInfo // storage for setup info
00083 {
00084     Boolean fAcceleratedMust;   // input: must renderer be accelerated?
00085     GLint aglAttributes[64];    // input: pixel format attributes always required (reset to what was actually allocated)
00086     SInt32 VRAM;                // input: minimum VRAM; output: actual (if successful otherwise input)
00087     SInt32 textureRAM;          // input: amount of texture RAM required on card; output: same (used in allcoation to ensure enough texture
00088     AGLPixelFormat    fmt;      // input: none; output pixel format...
00089     Boolean fDraggable;         // input: is window going to be dragable, 
00090                                 //        if so renderer check (accel, VRAM, textureRAM) will look at all renderers vice just the current one
00091                                 //        if window is not dragable renderer check will either check the single device or short 
00092                                 //            circuit to software if window spans multiple devices 
00093                                 //        software renderer is consider to have unlimited VRAM, unlimited textureRAM and to not be accelerated
00094 };
00095 typedef struct structGLWindowInfo structGLWindowInfo;
00096 typedef struct structGLWindowInfo * pstructGLWindowInfo;
00097 
00098 //-------------------------------------------------------------------------------------------- 
00099 
00100 struct recGLCap // structure to store minimum OpenGL capabilites across all displays and GPUs
00101 {
00102     Boolean f_ext_texture_rectangle; // is texture rectangle extension supported
00103     Boolean f_ext_client_storage; // is client storage extension supported
00104     Boolean f_ext_packed_pixel; // is packed pixel extension supported
00105     Boolean f_ext_texture_edge_clamp; // is SGI texture edge clamp extension supported
00106     Boolean f_gl_texture_edge_clamp; // is OpenGL texture edge clamp support (1.2+)
00107     unsigned long edgeClampParam; // the param that is passed to the texturing parmeteres
00108     long maxTextureSize; // the minimum max texture size across all GPUs
00109     long maxNOPTDTextureSize; // the minimum max texture size across all GPUs that support non-power of two texture dimensions
00110 };
00111 typedef struct recGLCap recGLCap;
00112 typedef recGLCap * pRecGLCap;
00113 
00114 struct recImage // OpenGL and image information associated with each window
00115 {
00116     // genric OpenGL stuff
00117     structGLWindowInfo glInfo;  // gl info used with SetupGL to build context
00118     AGLContext aglContext;      // the OpenGL context (read: state)
00119     GLuint fontList;            // the display list storing the bitmap font created for the context to display info
00120     
00121     Boolean fAGPTexturing;      // 10.1+ only: texture from AGP memory without loading to GPU
00122     
00123     // texture display stuff
00124     Boolean fNPOTTextures; // are we using Non-Power Of Two (NPOT) textures?
00125     Boolean fTileTextures; // are multiple tiled textures used to display image?
00126     Boolean fOverlapTextures; // do tiled textures overlapped to create correct filtering between tiles? (only applies if using tiled textures)
00127     Boolean fClientTextures; // 10.1+ only: texture from client memory
00128         
00129     unsigned char * pImageBuffer; // image buffer that contains data for image (disposed after loading into texture if not using client textures)
00130     long imageWidth; // height of orginal image
00131     long imageHeight; // width of orginal image
00132     float imageAspect; // width / height or aspect ratio of orginal image
00133     long imageDepth; // depth of image (after loading into gworld, will be either 32 or 16 bits)
00134     long textureX; // number of horizontal textures
00135     long textureY; // number of vertical textures
00136     long maxTextureSize; // max texture size for image
00137     GLuint * pTextureName; // array for texture names (# = textureX * textureY)
00138     long textureWidth; // total width of texels with cover image (including any border on image, but not internal texture overlaps)
00139     long textureHeight; // total height of texels with cover image (including any border on image, but not internal texture overlaps)
00140     float zoomX; // zoom from on texel = one pixel is 1.0
00141     float zoomY; // zoom from on texel = one pixel is 1.0
00142  };
00143 typedef struct recImage recImage; // typedef for easy declaration
00144 typedef recImage * pRecImage; // pointer type
00145 
00146 // ==================================
00147 
00148 // public function declarations -------------------------------------
00149 
00150 // Destroys drawable and context
00151 // Ouputs: *paglDraw, *paglContext should be 0 on exit
00152 // destorys a context that was associated with an existing window, window is left intacted
00153 OSStatus DestroyGLFromWindow (AGLContext* paglContext, pstructGLWindowInfo pcontextInfo);
00154 
00155 short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice);
00156 
00157 // disposes OpenGL context, and associated texture list
00158 OSStatus DisposeGLForWindow (WindowRef window);
00159 
00160 // builds the GL context and associated state for the window
00161 // loads image into a texture or textures
00162 // disposes of GWorld and image buffer when finished loading textures
00163 OSStatus BuildGLForWindow (WindowRef window);
00164 
00165 // Handle updating context for window moves and resizing
00166 OSStatus ResizeMoveGLWindow (WindowRef window);
00167 
00168 // main GL drawing routine, should be valid window passed in (will setupGL if require).  Draw image
00169 void DrawGL (WindowRef window);
00170 
00171 pRecGLCap gpOpenGLCaps; 
00172 
00173 // prototypes (internal/private) --------------------------------------------
00174 
00175 static Boolean CheckRenderer (GDHandle hGD, long *VRAM, long *textureRAM, GLint*  , Boolean fAccelMust);
00176 static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust);
00177 static void DumpCurrent (AGLDrawable* paglDraw, AGLContext* paglContext, pstructGLInfo pcontextInfo);
00178 static OSStatus BuildGLonWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext);
00179 
00180 static long GetNextTextureSize (long textureDimension, long maxTextureSize, Boolean textureRectangle);
00181 static long GetTextureNumFromTextureDim (long textureDimension, long maxTextureSize, Boolean texturesOverlap, Boolean textureRectangle);
00182 
00183 // ----------------------------------------------------------------------------------------
00184 
00185 // functions (internal/private) ---------------------------------------------
00186 
00187 #pragma mark -
00188 // --------------------------------------------------------------------------
00189 
00190 // central error reporting
00191 
00192 void ReportErrorNum (char * strError, long numError)
00193 {
00194     char errMsgPStr [257];
00195     
00196     errMsgPStr[0] = (char)snprintf (errMsgPStr+1, 255, "%s %ld (0x%lx)\n", strError, numError, numError); 
00197 
00198     // ensure we are faded in
00199     DebugStr ( (ConstStr255Param) errMsgPStr );
00200 }
00201 
00202 // --------------------------------------------------------------------------
00203 
00204 void ReportError (char * strError)
00205 {
00206     char errMsgPStr [257];
00207     
00208     errMsgPStr[0] = (char)snprintf (errMsgPStr+1, 255, "%s\n", strError); 
00209 
00210     // ensure we are faded in
00211     DebugStr ( (ConstStr255Param) errMsgPStr );
00212 }
00213 
00214 //-----------------------------------------------------------------------------------------------------------------------
00215 
00216 // if error dump agl errors to debugger string, return error
00217 
00218 OSStatus aglReportError (void)
00219 {
00220     GLenum err = aglGetError();
00221     if (AGL_NO_ERROR != err)
00222         ReportError ((char *)aglErrorString(err));
00223     // ensure we are returning an OSStatus noErr if no error condition
00224     if (err == AGL_NO_ERROR)
00225         return noErr;
00226     else
00227         return (OSStatus) err;
00228 }
00229 
00230 //-----------------------------------------------------------------------------------------------------------------------
00231 
00232 // if error dump gl errors to debugger string, return error
00233 
00234 OSStatus glReportError (void)
00235 {
00236     GLenum err = glGetError();
00237     switch (err)
00238     {
00239         case GL_NO_ERROR:
00240             break;
00241         case GL_INVALID_ENUM:
00242             ReportError ("GL Error: Invalid enumeration");
00243             break;
00244         case GL_INVALID_VALUE:
00245             ReportError ("GL Error: Invalid value");
00246             break;
00247         case GL_INVALID_OPERATION:
00248             ReportError ("GL Error: Invalid operation");
00249             break;
00250         case GL_STACK_OVERFLOW:
00251             ReportError ("GL Error: Stack overflow");
00252             break;
00253         case GL_STACK_UNDERFLOW:
00254             ReportError ("GL Error: Stack underflow");
00255             break;
00256         case GL_OUT_OF_MEMORY:
00257             ReportError ("GL Error: Out of memory");
00258             break;
00259     }
00260     // ensure we are returning an OSStatus noErr if no error condition
00261     if (err == GL_NO_ERROR)
00262         return noErr;
00263     else
00264         return (OSStatus) err;
00265 }
00266 
00267 //--------------------------------------------------------------------------------------------
00268 
00269 // functions (internal/private) ---------------------------------------------
00270 
00271 // CheckRenderer
00272 
00273 // looks at renderer attributes it has at least the VRAM is accelerated
00274 
00275 // Inputs:     hGD: GDHandle to device to look at
00276 //            pVRAM: pointer to VRAM in bytes required; out is actual VRAM if a renderer was found, otherwise it is the input parameter
00277 //            pTextureRAM:  pointer to texture RAM in bytes required; out is same (implementation assume VRAM returned by card is total so we add texture and VRAM)
00278 //            fAccelMust: do we check for acceleration
00279 
00280 // Returns: true if renderer for the requested device complies, false otherwise
00281 
00282 static Boolean CheckRenderer (GDHandle hGD, long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust)
00283 {
00284     AGLRendererInfo info, head_info;
00285     GLint inum;
00286     GLint dAccel = 0;
00287     GLint dVRAM = 0, dMaxVRAM = 0;
00288     Boolean canAccel = false, found = false;
00289     head_info = aglQueryRendererInfo(&hGD, 1);
00290     aglReportError ();
00291     if(!head_info)
00292     {
00293         ReportError ("aglQueryRendererInfo error");
00294         return false;
00295     }
00296     else
00297     {
00298         info = head_info;
00299         inum = 0;
00300         // see if we have an accelerated renderer, if so ignore non-accelerated ones
00301         // this prevents returning info on software renderer when actually we'll get the hardware one
00302         while (info)
00303         {    
00304             aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
00305             aglReportError ();
00306             if (dAccel)
00307                 canAccel = true;
00308             info = aglNextRendererInfo(info);
00309             aglReportError ();
00310             inum++;
00311         }
00312             
00313         info = head_info;
00314         inum = 0;
00315         while (info)
00316         {
00317             aglDescribeRenderer (info, AGL_ACCELERATED, &dAccel);
00318             aglReportError ();
00319             // if we can accel then we will choose the accelerated renderer 
00320             // how about compliant renderers???
00321             if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel)))
00322             {
00323                 aglDescribeRenderer (info, AGL_VIDEO_MEMORY, &dVRAM);    // we assume that VRAM returned is total thus add texture and VRAM required
00324                 aglReportError ();
00325                 if (dVRAM >= (*pVRAM + *pTextureRAM))
00326                 {
00327                     if (dVRAM >= dMaxVRAM) // find card with max VRAM
00328                     {
00329                         aglDescribeRenderer (info, AGL_DEPTH_MODES, pDepthSizeSupport);    // which depth buffer modes are supported
00330                         aglReportError ();
00331                         dMaxVRAM = dVRAM; // store max
00332                         found = true;
00333                     }
00334                 }
00335             }
00336             info = aglNextRendererInfo(info);
00337             aglReportError ();
00338             inum++;
00339         }
00340     }
00341     aglDestroyRendererInfo(head_info);
00342     if (found) // if we found a card that has enough VRAM and meets the accel criteria
00343     {
00344         *pVRAM = dMaxVRAM; // return VRAM
00345         return true;
00346     }
00347     // VRAM will remain to same as it did when sent in
00348     return false;
00349 }
00350 
00351 //-----------------------------------------------------------------------------------------------------------------------
00352 
00353 // CheckAllDeviceRenderers 
00354 
00355 // looks at renderer attributes and each device must have at least one renderer that fits the profile
00356 
00357 // Inputs:     pVRAM: pointer to VRAM in bytes required; out is actual min VRAM of all renderers found, otherwise it is the input parameter
00358 //            pTextureRAM:  pointer to texture RAM in bytes required; out is same (implementation assume VRAM returned by card is total so we add texture and VRAM)
00359 //            fAccelMust: do we check fro acceleration
00360 
00361 // Returns: true if any renderer for on each device complies (not necessarily the same renderer), false otherwise
00362 
00363 static Boolean CheckAllDeviceRenderers (long* pVRAM, long* pTextureRAM, GLint* pDepthSizeSupport, Boolean fAccelMust)
00364 {
00365     AGLRendererInfo info, head_info;
00366     GLint inum;
00367     GLint dAccel = 0;
00368     GLint dVRAM = 0, dMaxVRAM = 0;
00369     Boolean canAccel = false, found = false, goodCheck = true; // can the renderer accelerate, did we find a valid renderer for the device, are we still successfully on all the devices looked at
00370     long MinVRAM = 0x8FFFFFFF; // max long
00371     GDHandle hGD = GetDeviceList (); // get the first screen
00372     while (hGD && goodCheck)
00373     {
00374         head_info = aglQueryRendererInfo(&hGD, 1);
00375         aglReportError ();
00376         if(!head_info)
00377         {
00378             ReportError ("aglQueryRendererInfo error");
00379             return false;
00380         }
00381         else
00382         {
00383             info = head_info;
00384             inum = 0;
00385             // see if we have an accelerated renderer, if so ignore non-accelerated ones
00386             // this prevents returning info on software renderer when actually we'll get the hardware one
00387             while (info)
00388             {
00389                 aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
00390                 aglReportError ();
00391                 if (dAccel)
00392                     canAccel = true;
00393                 info = aglNextRendererInfo(info);
00394                 aglReportError ();
00395                 inum++;
00396             }
00397                 
00398             info = head_info;
00399             inum = 0;
00400             while (info)
00401             {    
00402                 aglDescribeRenderer(info, AGL_ACCELERATED, &dAccel);
00403                 aglReportError ();
00404                 // if we can accel then we will choose the accelerated renderer 
00405                 // how about compliant renderers???
00406                 if ((canAccel && dAccel) || (!canAccel && (!fAccelMust || dAccel)))
00407                 {
00408                     aglDescribeRenderer(info, AGL_VIDEO_MEMORY, &dVRAM);    // we assume that VRAM returned is total thus add texture and VRAM required
00409                     aglReportError ();
00410                     if (dVRAM >= (*pVRAM + *pTextureRAM))
00411                     {
00412                         if (dVRAM >= dMaxVRAM) // find card with max VRAM
00413                         {
00414                             aglDescribeRenderer(info, AGL_DEPTH_MODES, pDepthSizeSupport);    // which depth buffer modes are supported
00415                             aglReportError ();
00416                             dMaxVRAM = dVRAM; // store max
00417                             found = true;
00418                         }
00419                     }
00420                 }
00421                 info = aglNextRendererInfo(info);
00422                 aglReportError ();
00423                 inum++;
00424             }
00425         }
00426         aglDestroyRendererInfo(head_info);
00427         if (found) // if we found a card that has enough VRAM and meets the accel criteria
00428         {
00429             if (MinVRAM > dMaxVRAM)
00430                 MinVRAM = dMaxVRAM; // return VRAM
00431             
00432         }
00433         else
00434             goodCheck = false; // one device failed thus entire requirement fails
00435         hGD = GetNextDevice (hGD); // get next device
00436     } // while
00437     if (goodCheck) // we check all devices and each was good
00438     {
00439         *pVRAM = MinVRAM; // return VRAM
00440         return true;
00441     }
00442     return false; //at least one device failed to have mins
00443 }
00444 
00445 //-----------------------------------------------------------------------------------------------------------------------
00446 
00447 // DumpCurrent
00448 
00449 // Kills currently allocated context
00450 // does not care about being pretty (assumes display is likely faded)
00451 
00452 // Inputs:     paglDraw, paglContext: things to be destroyed
00453 
00454 void DumpCurrent (AGLDrawable* paglDraw, AGLContext* paglContext, pstructGLInfo pcontextInfo)
00455 {
00456     if (*paglContext)
00457     {
00458         aglSetCurrentContext (NULL);
00459         aglReportError ();
00460         aglSetDrawable (*paglContext, NULL);
00461         aglReportError ();
00462         aglDestroyContext (*paglContext);
00463         aglReportError ();
00464         *paglContext = NULL;
00465     }
00466     
00467     if (pcontextInfo->fmt)
00468     {
00469         aglDestroyPixelFormat (pcontextInfo->fmt); // pixel format is no longer needed
00470         aglReportError ();
00471     }
00472     pcontextInfo->fmt = 0;
00473 
00474     if (*paglDraw) // do not destory a window on DSp since there is no window built in X
00475         DisposeWindow (GetWindowFromPort (*paglDraw));
00476     *paglDraw = NULL;
00477 }
00478 
00479 #pragma mark -
00480 // --------------------------------------------------------------------------
00481 
00482 // BuildGLonWindow
00483 
00484 static OSStatus BuildGLonWindow (WindowPtr pWindow, AGLContext* paglContext, pstructGLWindowInfo pcontextInfo, AGLContext aglShareContext)
00485 {
00486     GDHandle hGD = NULL;
00487     GrafPtr cgrafSave = NULL;
00488     short numDevices;
00489     GLint depthSizeSupport;
00490     OSStatus err = noErr;
00491     
00492     if (!pWindow || !pcontextInfo)
00493     {
00494         ReportError ("NULL parameter passed to BuildGLonWindow.");
00495         return paramErr;
00496     }
00497     
00498     GetPort (&cgrafSave);
00499     SetPortWindowPort(pWindow);
00500 
00501     // check renderere VRAM and acceleration
00502     numDevices = FindGDHandleFromWindow (pWindow, &hGD);
00503     if (!pcontextInfo->fDraggable)     // if numDevices > 1 then we will only be using the software renderer otherwise check only window device
00504     {
00505         if ((numDevices > 1) || (numDevices == 0)) // this window spans mulitple devices thus will be software only
00506         {
00507             // software renderer
00508             // infinite VRAM, infinite textureRAM, not accelerated
00509             if (pcontextInfo->fAcceleratedMust)
00510             {
00511                 ReportError ("Unable to accelerate window that spans multiple devices");
00512                 return err;
00513             }
00514         }
00515         else // not draggable on single device
00516         {
00517             if (!CheckRenderer (hGD, &(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust))
00518             {
00519                 ReportError ("Renderer check failed");
00520                 return err;
00521             }
00522         }
00523     }
00524     // else draggable so must check all for support (each device should have at least one renderer that meets the requirements)
00525     else if (!CheckAllDeviceRenderers (&(pcontextInfo->VRAM), &(pcontextInfo->textureRAM), &depthSizeSupport, pcontextInfo->fAcceleratedMust))
00526     {
00527         ReportError ("Renderer check failed");
00528         return err;
00529     }
00530     
00531     // do agl
00532     if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL
00533     {
00534         ReportError ("OpenGL not installed");
00535         return noErr;
00536     }    
00537     // we successfully passed the renderer check
00538 
00539     if ((!pcontextInfo->fDraggable && (numDevices == 1)))  // not draggable on a single device
00540         pcontextInfo->fmt = aglChoosePixelFormat (&hGD, 1, pcontextInfo->aglAttributes); // get an appropriate pixel format
00541     else
00542         pcontextInfo->fmt = aglChoosePixelFormat (NULL, 0, pcontextInfo->aglAttributes); // get an appropriate pixel format
00543     aglReportError ();
00544     if (NULL == pcontextInfo->fmt) 
00545     {
00546         ReportError("Could not find valid pixel format");
00547         return noErr;
00548     }
00549 
00550     *paglContext = aglCreateContext (pcontextInfo->fmt, aglShareContext); // Create an AGL context
00551     if (AGL_BAD_MATCH == aglGetError())
00552         *paglContext = aglCreateContext (pcontextInfo->fmt, 0); // unable to sahre context, create without sharing
00553     aglReportError ();
00554     if (NULL == *paglContext) 
00555     {
00556         ReportError ("Could not create context");
00557         return noErr;
00558     }
00559     
00560     if (!aglSetDrawable (*paglContext, GetWindowPort (pWindow))) // attach the CGrafPtr to the context
00561         return aglReportError ();
00562     
00563     if(!aglSetCurrentContext (*paglContext)) // make the context the current context
00564         return aglReportError ();
00565 
00566     SetPort (cgrafSave);
00567 
00568     return err;
00569 }
00570 
00571 #pragma mark -
00572 
00573 // functions (public) -------------------------------------------------------
00574 
00575 // DestroyGLFromWindow
00576 
00577 // Destroys context that waas allocated with BuildGLonWindow
00578 // Ouputs: *paglContext should be NULL on exit
00579 
00580 OSStatus DestroyGLFromWindow (AGLContext* paglContext, pstructGLWindowInfo pcontextInfo)
00581 {
00582     OSStatus err;
00583     
00584     if ((!paglContext) || (!*paglContext))
00585         return paramErr; // not a valid context
00586     glFinish ();
00587     aglSetCurrentContext (NULL);
00588     err = aglReportError ();
00589     aglSetDrawable (*paglContext, NULL);
00590     err = aglReportError ();
00591     aglDestroyContext (*paglContext);
00592     err = aglReportError ();
00593     *paglContext = NULL;
00594 
00595     if (pcontextInfo->fmt)
00596     {
00597         aglDestroyPixelFormat (pcontextInfo->fmt); // pixel format is no longer valid
00598         err = aglReportError ();
00599     }
00600     pcontextInfo->fmt = 0;
00601     
00602     return err;
00603 }
00604 
00605 //-----------------------------------------------------------------------------------------------------------------------
00606 
00607 // GetWindowDevice
00608 
00609 // Inputs:    a valid WindowPtr
00610 
00611 // Outputs:    the GDHandle that that window is mostly on
00612 
00613 // returns the number of devices that the windows content touches
00614 
00615 short FindGDHandleFromWindow (WindowPtr pWindow, GDHandle * phgdOnThisDevice)
00616 {
00617     GrafPtr pgpSave;
00618     Rect rectWind, rectSect;
00619     long greatestArea, sectArea;
00620     short numDevices = 0;
00621     GDHandle hgdNthDevice;
00622     
00623     if (!pWindow || !phgdOnThisDevice)
00624         return 0;
00625         
00626     *phgdOnThisDevice = NULL;
00627     
00628     GetPort (&pgpSave);
00629     SetPortWindowPort (pWindow);
00630     
00631 
00632     GetWindowPortBounds (pWindow, &rectWind);
00633     LocalToGlobal ((Point*)& rectWind.top);    // convert to global coordinates
00634     LocalToGlobal ((Point*)& rectWind.bottom);
00635     hgdNthDevice = GetDeviceList ();
00636     greatestArea = 0;
00637     // check window against all gdRects in gDevice list and remember 
00638     //  which gdRect contains largest area of window}
00639     while (hgdNthDevice)
00640     {
00641         if (TestDeviceAttribute (hgdNthDevice, screenDevice))
00642             if (TestDeviceAttribute (hgdNthDevice, screenActive))
00643             {
00644                 // The SectRect routine calculates the intersection 
00645                 //  of the window rectangle and this gDevice 
00646                 //  rectangle and returns TRUE if the rectangles intersect, 
00647                 //  FALSE if they don't.
00648                 SectRect (&rectWind, &(**hgdNthDevice).gdRect, &rectSect);
00649                 // determine which screen holds greatest window area
00650                 //  first, calculate area of rectangle on current device
00651                 sectArea = (long) (rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top);
00652                 if (sectArea > 0)
00653                     numDevices++;
00654                 if (sectArea > greatestArea)
00655                 {
00656                     greatestArea = sectArea; // set greatest area so far
00657                     *phgdOnThisDevice = hgdNthDevice; // set zoom device
00658                 }
00659                 hgdNthDevice = GetNextDevice(hgdNthDevice);
00660             }
00661     }
00662     
00663     SetPort (pgpSave);
00664     return numDevices;
00665 }
00666 
00667 //--------------------------------------------------------------------------------------------
00668 // private
00669 
00670 // returns the largest power of 2 texture <= textureDimension
00671 // or in the case of texture rectangle returns the next texture size (can be non-power of two)
00672 
00673 static long GetNextTextureSize (long textureDimension, long maxTextureSize, Boolean textureRectangle)
00674 {
00675     long targetTextureSize = maxTextureSize; // start at max texture size
00676     if (textureRectangle)
00677     {
00678         if (textureDimension >= targetTextureSize) // the texture dimension is greater than the target texture size (i.e., it fits)
00679             return targetTextureSize; // return corresponding texture size
00680         else
00681             return textureDimension; // jusr return the dimension
00682     }
00683     else
00684     {
00685         do // while we have txture sizes check for texture value being equal or greater
00686         {  
00687             if (textureDimension >= targetTextureSize) // the texture dimension is greater than the target texture size (i.e., it fits)
00688                 return targetTextureSize; // return corresponding texture size
00689         }
00690         while (targetTextureSize >>= 1); // step down to next texture size smaller
00691     }
00692     return 0; // no textures fit so return zero
00693 }
00694 
00695 // ---------------------------------
00696 
00697 // returns the nuber of textures need to represent a size of textureDimension given
00698 // requirement for power of 2 textures as the maximum texture size
00699 // for the overlap case each texture effectively covers two less pixels so must iterate through using whole statement
00700 
00701 static long GetTextureNumFromTextureDim (long textureDimension, long maxTextureSize, Boolean texturesOverlap, Boolean textureRectangle) 
00702 {
00703     // start at max texture size 
00704     // loop through each texture size, removing textures in turn which are less than the remaining texture dimension
00705     // each texture has 2 pixels of overlap (one on each side) thus effective texture removed is 2 less than texture size
00706     
00707     long i = 0; // initially no textures
00708     long bitValue = maxTextureSize; // start at max texture size
00709     long texOverlapx2 = texturesOverlap ? 2 : 0;
00710     textureDimension -= texOverlapx2; // ignore texture border since we are using effective texure size (by subtracting 2 from the initial size)
00711     if (textureRectangle)
00712     {
00713         // count number of full textures
00714         while (textureDimension > (bitValue - texOverlapx2)) // while our texture dimension is greater than effective texture size (i.e., minus the border)
00715         {
00716             i++; // count a texture
00717             textureDimension -= bitValue - texOverlapx2; // remove effective texture size
00718         }
00719         // add one partial texture
00720         i++; 
00721     }
00722     else
00723     {
00724         do
00725         {
00726             while (textureDimension >= (bitValue - texOverlapx2)) // while our texture dimension is greater than effective texture size (i.e., minus the border)
00727             {
00728                 i++; // count a texture
00729                 textureDimension -= bitValue - texOverlapx2; // remove effective texture size
00730             }
00731         }
00732         while ((bitValue >>= 1) > texOverlapx2); // step down to next texture while we are greater than two (less than 4 can't be used due to 2 pixel overlap)
00733     if (textureDimension > 0x0) // if any textureDimension is left there is an error, because we can't texture these small segments and in anycase should not have image pixels left
00734         ReportErrorNum ("GetTextureNumFromTextureDim error: Texture to small to draw, should not ever get here, texture size remaining:", textureDimension);
00735     }
00736     return i; // return textures counted
00737 } 
00738 
00739 #pragma mark -
00740 // ==================================
00741 // public
00742 
00743 // disposes OpenGL context, and associated texture list
00744 
00745 OSStatus DisposeGLForWindow (WindowRef window)
00746 {
00747     if (window)
00748     {
00749         pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get gl data stored in refcon
00750         SetWRefCon (window, 0); // ensure the refcon is not used again
00751         if (NULL == pWindowInfo) // if this is non-existant
00752             return paramErr; // then drop out
00753         if (NULL != pWindowInfo->aglContext)
00754         {
00755             aglSetCurrentContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current
00756             aglUpdateContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current
00757             glFinish (); // ensure all gl commands are complete
00758             glDeleteTextures (pWindowInfo->textureX * pWindowInfo->textureY, pWindowInfo->pTextureName); // delete the complete set of textures used for the window
00759             DestroyGLFromWindow (&pWindowInfo->aglContext, &pWindowInfo->glInfo); // preoperly destroy GL context and any associated structures
00760             pWindowInfo->aglContext = NULL; // ensure we don't use invlad context
00761         }
00762         if (NULL != pWindowInfo->pTextureName)
00763         {
00764             DisposePtr ((Ptr) pWindowInfo->pTextureName); // dispose of the allocate4d texture name storage
00765             pWindowInfo->pTextureName = NULL; // ensure we do not use it again
00766         }
00767         if (pWindowInfo->pImageBuffer) // MUST preserve the buffer if texturing from client memory
00768         {
00769             //DisposePtr ((Ptr) pWindowInfo->pImageBuffer); // or image buffer
00770             pWindowInfo->pImageBuffer = NULL;
00771         }
00772         DisposePtr ((Ptr) pWindowInfo);
00773         return noErr; // we are good to go
00774     }
00775     else
00776         return paramErr; // NULL window ref passed in
00777 }
00778 
00779 // ---------------------------------
00780 
00781 // builds the GL context and associated state for the window
00782 // loads image into a texture or textures
00783 // disposes of GWorld and image buffer when finished loading textures
00784 
00785 OSStatus BuildGLForWindow (WindowRef window)
00786 {
00787     GrafPtr portSave = NULL; // port which is set on entrance to this routine
00788     pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // the info structure for the window stored in the refcon
00789     short i; // iterator
00790     GLenum textureTarget = GL_TEXTURE_2D;
00791    
00792     if (!pWindowInfo->aglContext) // if we get here and do not have a context built, build one
00793     {
00794         GetPort (&portSave);    // save current port
00795         SetPort ((GrafPtr) GetWindowPort (window)); // set port to the current window
00796         // set parameters for Carbon SetupGL
00797         pWindowInfo->glInfo.fAcceleratedMust = false; // must renderer be accelerated?
00798         pWindowInfo->glInfo.VRAM = 0 * 1048576; // minimum VRAM (if not zero this is always required)
00799         pWindowInfo->glInfo.textureRAM = 0 * 1048576; // minimum texture RAM (if not zero this is always required)
00800            pWindowInfo->glInfo.fDraggable = true; // is this a draggable window
00801         pWindowInfo->glInfo.fmt = 0; // output pixel format
00802         
00803         i = 0; // first attribute in array
00804         pWindowInfo->glInfo.aglAttributes [i++] = AGL_RGBA; // RGB + Alpha pixels
00805         pWindowInfo->glInfo.aglAttributes [i++] = AGL_DOUBLEBUFFER; // doble buffered context
00806         pWindowInfo->glInfo.aglAttributes [i++] = AGL_ACCELERATED; // require hardware acceleration
00807         pWindowInfo->glInfo.aglAttributes [i++] = AGL_NO_RECOVERY; // 10.0.4 has problems with the GL (disregards UNPACK_ROW_LENGTH) resulting from using no recovery
00808                                                                    // normally we would use no recovery to ensure the minimum pixel size textures are stored by GL.
00809         pWindowInfo->glInfo.aglAttributes [i++] = AGL_NONE; // end parameter list
00810         BuildGLonWindow (window, &(pWindowInfo->aglContext), &(pWindowInfo->glInfo), NULL); // build opengl context for our window
00811         if (!pWindowInfo->aglContext) // if could not create context
00812             DestroyGLFromWindow (&pWindowInfo->aglContext, &pWindowInfo->glInfo); // ensure context is destroyed correctly
00813         else // we have a valid context
00814         {
00815             GLint swap = 0; // swap interval (i.e., VBL sync) setting 1 = sync, 0 = no sync
00816             Rect rectPort; // window port rectangle
00817             long width = pWindowInfo->imageWidth, height = pWindowInfo->imageHeight; // image width and height
00818             GDHandle device; // GDevice to find the constrain the window to
00819             Rect deviceRect, availRect, rect; // rect of device which window is on (mostly, area wise at least). avialable area for window (minus dock and menu if req), working rect
00820 
00821             GetWindowGreatestAreaDevice (window, kWindowContentRgn, &device, &deviceRect); // find device the window is mostly on
00822             GetAvailableWindowPositioningBounds (device, &availRect); //  get the geretest available area for te windoew (mminus doc and menu if applicable)
00823             if (width > (availRect.right - availRect.left)) // adjust window width if it is greater than available area (orginally set to image width, see above)
00824                 width = (availRect.right - availRect.left);
00825             if (height > (availRect.bottom - availRect.top)) // adjust window height if it is greater than available area (orginally set to image width, see above)
00826                 height = (availRect.bottom - availRect.top);
00827             SizeWindow (window, (short) width, (short) height, true); // size the window to new width and height
00828             ConstrainWindowToScreen(window, kWindowStructureRgn, kWindowConstrainMayResize, NULL, &rect); // ensure window structure region is on the screen
00829             GetWindowPortBounds (window, &rectPort); // get port rect for viewport reset
00830 
00831             aglSetCurrentContext (pWindowInfo->aglContext); // set our GL context to this one
00832             aglUpdateContext (pWindowInfo->aglContext); // update the context to account for the resize
00833             InvalWindowRect (window, &rectPort); // inval the entire window to ensure we get a redraw
00834             glViewport (0, 0, rectPort.right - rectPort.left, rectPort.bottom - rectPort.top); // reset viewport to entier window area
00835 
00836             aglSetInteger (pWindowInfo->aglContext, AGL_SWAP_INTERVAL, &swap); // set swap interval to account for vbl syncing or not
00837             
00838             // set correct texture target // if building on 10.0 or 9 this will be undefined
00839         #ifdef GL_TEXTURE_RECTANGLE_EXT
00840             if (pWindowInfo->fNPOTTextures)
00841                 textureTarget = GL_TEXTURE_RECTANGLE_EXT;
00842         #endif
00843             
00844             // Set texture mapping parameters
00845             glEnable (textureTarget); // enable texturing
00846                 
00847             glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // set clear color buffer to dark gray
00848             glClear (GL_COLOR_BUFFER_BIT); // clear just to color buffer
00849             aglSwapBuffers (pWindowInfo->aglContext); // swap the cleared buffer to front
00850     
00851             //GetFNum ("\pMonaco", &fNum); // get font number for named font
00852             //pWindowInfo->fontList = BuildFontGL (pWindowInfo->aglContext, fNum, normal, 9); // build display list for fonts for this context (see aglString for more info)
00853             
00854             // if we can use texture rectangle // if building on 10.0 or 9 this will be undefined
00855         #ifdef GL_TEXTURE_RECTANGLE_EXT
00856             if (pWindowInfo->fNPOTTextures)
00857                 glEnable(GL_TEXTURE_RECTANGLE_EXT);
00858         #endif
00859             if (pWindowInfo->fAGPTexturing)
00860                 glTextureRangeAPPLE(textureTarget, pWindowInfo->textureHeight * pWindowInfo->textureWidth * (pWindowInfo->imageDepth >> 3), pWindowInfo->pImageBuffer);
00861             glPixelStorei (GL_UNPACK_ROW_LENGTH, pWindowInfo->textureWidth); // set image width in groups (pixels), accounts for border this ensures proper image alignment row to row
00862             // get number of textures x and y
00863                 // extract the number of horiz. textures needed to tile image
00864             pWindowInfo->textureX = GetTextureNumFromTextureDim (pWindowInfo->textureWidth, pWindowInfo->maxTextureSize, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); 
00865                 // extract the number of horiz. textures needed to tile image
00866             pWindowInfo->textureY = GetTextureNumFromTextureDim (pWindowInfo->textureHeight, pWindowInfo->maxTextureSize, pWindowInfo->fOverlapTextures, pWindowInfo->fNPOTTextures); 
00867             pWindowInfo->pTextureName = (GLuint *) NewPtrClear ((long) sizeof (GLuint) * pWindowInfo->textureX * pWindowInfo->textureY); // allocate storage for texture name lists
00868             glGenTextures (pWindowInfo->textureX * pWindowInfo->textureY, pWindowInfo->pTextureName); // generate textures names need to support tiling
00869             {
00870                 long x, y, k = 0, offsetY, offsetX = 0, currWidth, currHeight; // texture iterators, texture name iterator, image offsets for tiling, current texture width and height
00871                 for (x = 0; x < pWindowInfo->textureX; x++) // for all horizontal textures
00872                 {
00873                     currWidth = GetNextTextureSize (pWindowInfo->textureWidth - offsetX, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures); // use remaining to determine next texture size 
00874                                                                                                                     // (basically greatest power of 2 which fits into remaining space)
00875                     offsetY = 0; // reset vertical offest for every column
00876                     for (y = 0; y < pWindowInfo->textureY; y++) // for all vertical textures
00877                     {
00878                         // buffer pointer is at base + rows * row size + columns
00879                         unsigned char * pBuffer = pWindowInfo->pImageBuffer + 
00880                                                    offsetY * pWindowInfo->textureWidth * (pWindowInfo->imageDepth >> 3) + 
00881                                                    offsetX * (pWindowInfo->imageDepth >> 3);
00882                         currHeight = GetNextTextureSize (pWindowInfo->textureHeight - offsetY, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures); // use remaining to determine next texture size
00883                         glBindTexture (textureTarget, pWindowInfo->pTextureName[k++]);
00884                         if (pWindowInfo->fAGPTexturing) {
00885                             glTexParameterf (textureTarget, GL_TEXTURE_PRIORITY, 0.0f); // AGP texturing
00886                             glTexParameteri (textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_SHARED_APPLE);
00887                         }
00888                         else
00889                             glTexParameterf (textureTarget, GL_TEXTURE_PRIORITY, 1.0f);
00890                             
00891                     #ifdef GL_UNPACK_CLIENT_STORAGE_APPLE
00892                         if (pWindowInfo->fClientTextures)
00893                             glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, 1);
00894                         else
00895                             glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, 0);
00896                     #endif
00897 
00898                         glTexParameteri (textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00899                         glTexParameteri (textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00900                         glTexParameteri (textureTarget, GL_TEXTURE_WRAP_S, gpOpenGLCaps->edgeClampParam);
00901                         glTexParameteri (textureTarget, GL_TEXTURE_WRAP_T, gpOpenGLCaps->edgeClampParam);
00902                         glReportError (); // report any errors so far
00903                         glTexImage2D (textureTarget, 0, GL_RGBA, currWidth, currHeight, 0, 
00904                                       GL_BGRA_EXT, pWindowInfo->imageDepth == 32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV, 
00905                                       pBuffer); // texture with current width and height at pBuffer location in image buffer with image size as GL_UNPACK_ROW_LENGTH
00906                         glReportError (); // report any errors
00907                         offsetY += currHeight - 2 * pWindowInfo->fOverlapTextures; // offset in for the amount of texture used, 
00908                                                                                        //  since we are overlapping the effective texture used is 2 texels less than texture width
00909                     }
00910                     offsetX += currWidth - 2 * pWindowInfo->fOverlapTextures; // offset in for the amount of texture used, 
00911                                                                               //  since we are overlapping the effective texture used is 2 texels less than texture width
00912                 }
00913             }
00914             if (false == pWindowInfo->fClientTextures) // MUST preserve the buffer if texturing from client memory
00915             {
00916                 DisposePtr ((Ptr) pWindowInfo->pImageBuffer); // or image buffer
00917                 pWindowInfo->pImageBuffer = NULL;
00918             }
00919         }
00920         SetPort (portSave); //reset port
00921     }
00922     return noErr; // we done
00923 }
00924 
00925 // ---------------------------------
00926 
00927 // Handle updating context for window moves and resizing
00928 
00929 OSStatus ResizeMoveGLWindow (WindowRef window)
00930 {
00931     OSStatus err = noErr; // no errors to start
00932     Rect rectPort; // new port rect
00933     pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get GL info;
00934     if (window && pWindowInfo) // if we have a window
00935     {
00936         GetWindowPortBounds (window, &rectPort);
00937         pWindowInfo->zoomX = (float) (rectPort.right - rectPort.left) / (float) pWindowInfo->imageWidth;
00938         pWindowInfo->zoomY = (float) (rectPort.bottom - rectPort.top) / (float) pWindowInfo->imageHeight;
00939 
00940         if (!aglUpdateContext (pWindowInfo->aglContext)) // update the context to ensure gl knows about the move or resize
00941                aglReportError (); // report any error with update context
00942         if (noErr != err)
00943             ReportErrorNum ("ResizeMoveGLWindow error with InvalWindowRect on window: ", err);  // should not get erro here, but who knows
00944         err = InvalWindowRect (window, &rectPort);
00945     }
00946     else
00947         err = paramErr; // bad window
00948     return err; // return any error 
00949 }
00950 
00951 // ---------------------------------
00952 
00953 // main GL drawing routine, should be valid window passed in (will setupGL if require).  Draw image
00954 
00955 void DrawGL (WindowRef window)
00956 {
00957     Rect rectPort; // rectangle for port
00958     pRecImage pWindowInfo; // the gl info for the target window 
00959     long width, height; // width and height or the port and the row of the raster position
00960     long effectiveTextureMod = 0; // texture size modification (inset) to account for borders
00961     long x, y, k = 0, offsetY, offsetX = 0, currTextureWidth, currTextureHeight;
00962     GLenum textureTarget = GL_TEXTURE_2D;
00963     
00964     if (NULL == window) // if we do not have a window
00965         return; // drop out
00966     pWindowInfo = (pRecImage) GetWRefCon (window); // get the gl info for the window
00967     if (NULL == pWindowInfo) // if this is non-existant
00968         return; // then drop out
00969     if (NULL == pWindowInfo->aglContext) // try to buld the context if we don't have one (safety check)
00970         BuildGLForWindow (window);
00971     if (NULL == pWindowInfo->aglContext) // if we still don't have one then drop out
00972         return;
00973         
00974     if (pWindowInfo->fOverlapTextures)
00975         effectiveTextureMod = 2; // if we overlap then we need to inset the textures passed to the drawing code
00976     // set texture target
00977 #ifdef GL_TEXTURE_RECTANGLE_EXT
00978     if (pWindowInfo->fNPOTTextures)
00979         textureTarget = GL_TEXTURE_RECTANGLE_EXT;
00980 #endif
00981 
00982     aglSetCurrentContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current
00983     aglUpdateContext (pWindowInfo->aglContext); // ensaure the context we are working with is set to current
00984 
00985     GetWindowPortBounds (window, &rectPort); // get the current port (window) bounds
00986     width = rectPort.right - rectPort.left; // find width
00987     height = rectPort.bottom - rectPort.top; // and height
00988     glViewport (0, 0, width, height); // set the viewport to cover entire window
00989     
00990     glMatrixMode (GL_PROJECTION); // set projection matrix
00991     glLoadIdentity (); // to indetity
00992     glMatrixMode (GL_MODELVIEW); // set modelview matrix
00993     glLoadIdentity (); // to identity
00994     glReportError (); // report any GL errors so far
00995     
00996     // set the model view matrix for an orthographic view scaled to one screen pixel equal image pixel (independent of image zoom)
00997     glScalef (2.0f / width, -2.0f /  height, 1.0f); // scale to port per pixel scale
00998     //glTranslatef (pWindowInfo->centerX, pWindowInfo->centerY, 0.0f); // translate for image movement
00999     //glRotatef (0.0f, 0.0f, 0.0f, 1.0f); // ratate matrix for image rotation
01000     glReportError (); // report any GL errors
01001     
01002     glClear (GL_COLOR_BUFFER_BIT); // clear the color buffer before drawing
01003 
01004     // draw image
01005     glEnable (textureTarget); // enable texturing
01006     glColor3f (1.0f, 1.0f, 1.0f); // white polygons
01007     // offset x and y are used to draw the polygon and need to represent the texture effective edges (without borders)
01008     // so walk the texture size images adjusting for each border
01009     for (x = 0; x < pWindowInfo->textureX; x++) // for all horizontal textures
01010     {
01011         // use remaining to determine next texture size
01012         currTextureWidth = GetNextTextureSize (pWindowInfo->textureWidth - offsetX, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // current effective texture width for drawing
01013         offsetY = 0; // start at top
01014         for (y = 0; y < pWindowInfo->textureY; y++) // for a complete column
01015         {
01016             // use remaining to determine next texture size
01017             currTextureHeight = GetNextTextureSize (pWindowInfo->textureHeight - offsetY, pWindowInfo->maxTextureSize, pWindowInfo->fNPOTTextures) - effectiveTextureMod; // effective texture height for drawing
01018             glBindTexture(textureTarget, pWindowInfo->pTextureName[k++]); // work through textures in same order as stored, setting each texture name as current in turn
01019             if (!pWindowInfo->fAGPTexturing)
01020                 glTexSubImage2D(textureTarget, 0, 0, 0, currTextureWidth, currTextureHeight, GL_BGRA, pWindowInfo->imageDepth == 32 ? GL_UNSIGNED_INT_8_8_8_8_REV : GL_UNSIGNED_SHORT_1_5_5_5_REV, pWindowInfo->pImageBuffer);
01021             glReportError (); // report any errors
01022             {
01023                 float endX = pWindowInfo->fTileTextures ? currTextureWidth + offsetX : pWindowInfo->imageWidth;
01024                 float endY = pWindowInfo->fTileTextures ? currTextureHeight + offsetY : pWindowInfo->imageHeight;
01025                 float startXDraw = (offsetX - pWindowInfo->imageWidth * 0.5f) * pWindowInfo->zoomX; // left edge of poly: offset is in image local coordinates convert to world coordinates
01026                 float endXDraw = (endX - pWindowInfo->imageWidth * 0.5f) * pWindowInfo->zoomX; // right edge of poly: offset is in image local coordinates convert to world coordinates
01027                 float startYDraw = (offsetY - pWindowInfo->imageHeight * 0.5f) * pWindowInfo->zoomY; // top edge of poly: offset is in image local coordinates convert to world coordinates
01028                 float endYDraw = (endY - pWindowInfo->imageHeight * 0.5f) * pWindowInfo->zoomY; // bottom edge of poly: offset is in image local coordinates convert to world coordinates
01029                 float texOverlap =  pWindowInfo->fOverlapTextures ? 1.0f : 0.0f; // size of texture overlap, switch based on whether we are using overlap or not
01030                 float startXTexCoord = texOverlap / (currTextureWidth + 2.0f * texOverlap); // texture right edge coordinate (stepped in one pixel for border if required)
01031                 float endXTexCoord = 1.0f - startXTexCoord; // texture left edge coordinate (stepped in one pixel for border if required)
01032                 float startYTexCoord = texOverlap / (currTextureHeight + 2.0f * texOverlap); // texture top edge coordinate (stepped in one pixel for border if required)
01033                 float endYTexCoord = 1.0f - startYTexCoord; // texture bottom edge coordinate (stepped in one pixel for border if required)
01034                 if (pWindowInfo->fNPOTTextures)
01035                 {
01036                     startXTexCoord = texOverlap; // texture right edge coordinate (stepped in one pixel for border if required)
01037                     endXTexCoord = currTextureWidth + texOverlap; // texture left edge coordinate (stepped in one pixel for border if required)
01038                     startYTexCoord = texOverlap; // texture top edge coordinate (stepped in one pixel for border if required)
01039                     endYTexCoord = currTextureHeight + texOverlap; // texture bottom edge coordinate (stepped in one pixel for border if required)
01040                 }
01041                 if (endX > (pWindowInfo->imageWidth + 0.5)) // handle odd image sizes, (+0.5 is to ensure there is no fp resolution problem in comparing two fp numbers)
01042                 {
01043                     endXDraw = (pWindowInfo->imageWidth * 0.5f) * pWindowInfo->zoomX; // end should never be past end of image, so set it there
01044                     if (pWindowInfo->fNPOTTextures)
01045                         endXTexCoord -= 1.0f;
01046                     else
01047                         endXTexCoord = 1.0f -  2.0f * startXTexCoord; // for the last texture in odd size images there are two texels of padding so step in 2
01048                 }
01049                 if (endY > (pWindowInfo->imageHeight + 0.5f)) // handle odd image sizes, (+0.5 is to ensure there is no fp resolution problem in comparing two fp numbers)
01050                 {
01051                     endYDraw = (pWindowInfo->imageHeight * 0.5f) * pWindowInfo->zoomY; // end should never be past end of image, so set it there
01052                     if (pWindowInfo->fNPOTTextures)
01053                         endYTexCoord -= 1.0f;
01054                     else
01055                         endYTexCoord = 1.0f -  2.0f * startYTexCoord; // for the last texture in odd size images there are two texels of padding so step in 2
01056                 }
01057                 
01058                 glBegin (GL_TRIANGLE_STRIP); // draw either tri strips of line strips
01059                     glTexCoord2f (startXTexCoord, startYTexCoord); // draw upper left in world coordinates
01060                     glVertex3d (startXDraw, startYDraw, 0.0);
01061 
01062                     glTexCoord2f (endXTexCoord, startYTexCoord); // draw lower left in world coordinates
01063                     glVertex3d (endXDraw, startYDraw, 0.0);
01064 
01065                     glTexCoord2f (startXTexCoord, endYTexCoord); // draw upper right in world coordinates
01066                     glVertex3d (startXDraw, endYDraw, 0.0);
01067 
01068                     glTexCoord2f (endXTexCoord, endYTexCoord); // draw lower right in world coordinates
01069                     glVertex3d (endXDraw, endYDraw, 0.0);
01070                 glEnd();
01071                 
01072             }
01073 
01075 
01076             glReportError (); // report any errors
01077             offsetY += currTextureHeight; // offset drawing position for next texture vertically
01078         }
01079         offsetX += currTextureWidth; // offset drawing position for next texture horizontally
01080     }
01081     glReportError (); // report any errors
01082 
01083     glDisable (textureTarget); // done with texturing
01084         
01085     aglSwapBuffers (pWindowInfo->aglContext);
01086 }
01087 
01088 // finds the minimum OpenGL capabilites across all displays and GPUs attached to machine.
01089 
01090 static void FindMinimumOpenGLCapabilities (pRecGLCap pOpenGLCaps)
01091 {
01092     WindowPtr pWin = NULL; 
01093     Rect rectWin = {0, 0, 10, 10};
01094     GLint attrib[] = { AGL_RGBA, AGL_NONE };
01095     AGLPixelFormat fmt = NULL;
01096     AGLContext ctx = NULL;
01097     GLint deviceMaxTextureSize = 0, NPOTDMaxTextureSize = 0;
01098     
01099     if (NULL != gpOpenGLCaps)
01100     {
01101         // init desired caps to max values
01102         pOpenGLCaps->f_ext_texture_rectangle = true;
01103         pOpenGLCaps->f_ext_client_storage = true;
01104         pOpenGLCaps->f_ext_packed_pixel = true;
01105         pOpenGLCaps->f_ext_texture_edge_clamp = true;
01106         pOpenGLCaps->f_gl_texture_edge_clamp = true;
01107         pOpenGLCaps->maxTextureSize = 0x7FFFFFFF;
01108         pOpenGLCaps->maxNOPTDTextureSize = 0x7FFFFFFF;
01109 
01110         // build window
01111         pWin = NewCWindow (0L, &rectWin, NULL, false,
01112                 plainDBox, (WindowPtr) -1L, true, 0L);
01113                 
01114         // build context
01115         fmt = aglChoosePixelFormat(NULL, 0, attrib);
01116         if (fmt)
01117             ctx = aglCreateContext(fmt, NULL);
01118         if (ctx)
01119         {
01120             GDHandle hgdNthDevice;
01121             
01122             aglSetDrawable(ctx, GetWindowPort (pWin));
01123             aglSetCurrentContext(ctx);
01124             
01125             // for each display
01126             hgdNthDevice = GetDeviceList ();
01127             while (hgdNthDevice)
01128             {
01129                 if (TestDeviceAttribute (hgdNthDevice, screenDevice))
01130                     if (TestDeviceAttribute (hgdNthDevice, screenActive))
01131                     {
01132                         // move window to display
01133                         MoveWindow (pWin, (**hgdNthDevice).gdRect.left + 5, (**hgdNthDevice).gdRect.top + 5, false);
01134                         aglUpdateContext(ctx);
01135                         
01136                         // for each cap (this can obviously be expanded)
01137                         // if this driver/GPU/display is less capable
01138                             // save this minimum capability
01139                         {
01140                             // get strings
01141                             enum { kShortVersionLength = 32 };
01142                             const GLubyte * strVersion = glGetString (GL_VERSION); // get version string
01143                             const GLubyte * strExtension = glGetString (GL_EXTENSIONS);    // get extension string
01144                             
01145                             // get just the non-vendor specific part of version string
01146                             GLubyte strShortVersion [kShortVersionLength];
01147                             short i = 0;
01148                             while ((((strVersion[i] <= '9') && (strVersion[i] >= '0')) || (strVersion[i] == '.')) && (i < kShortVersionLength)) // get only basic version info (until first space)
01149                                 strShortVersion [i] = strVersion[i++];
01150                             strShortVersion [i] = 0; //truncate string
01151                             
01152                             // compare capabilities based on extension string and GL version
01153                             pOpenGLCaps->f_ext_texture_rectangle = 
01154                                 pOpenGLCaps->f_ext_texture_rectangle && (NULL != strstr ((const char *) strExtension, "GL_EXT_texture_rectangle"));
01155                             pOpenGLCaps->f_ext_client_storage = 
01156                                 pOpenGLCaps->f_ext_client_storage && (NULL != strstr ((const char *) strExtension, "GL_APPLE_client_storage"));
01157                             pOpenGLCaps->f_ext_packed_pixel = 
01158                                 pOpenGLCaps->f_ext_packed_pixel && (NULL != strstr ((const char *) strExtension, "GL_APPLE_packed_pixel"));
01159                             pOpenGLCaps->f_ext_texture_edge_clamp = 
01160                                 pOpenGLCaps->f_ext_texture_edge_clamp && (NULL != strstr ((const char *) strExtension, "GL_SGIS_texture_edge_clamp"));
01161                             pOpenGLCaps->f_gl_texture_edge_clamp = 
01162                                 pOpenGLCaps->f_gl_texture_edge_clamp && (!strstr ((const char *) strShortVersion, "1.0") && !strstr ((const char *) strShortVersion, "1.1")); // if not 1.0 and not 1.1 must be 1.2 or greater
01163                             
01164                             // get device max texture size
01165                             glGetIntegerv (GL_MAX_TEXTURE_SIZE, &deviceMaxTextureSize);
01166                             if (deviceMaxTextureSize < pOpenGLCaps->maxTextureSize)
01167                                 pOpenGLCaps->maxTextureSize = deviceMaxTextureSize;
01168                             // get max size of non-power of two texture on devices which support
01169                             if (NULL != strstr ((const char *) strExtension, "GL_EXT_texture_rectangle"))
01170                             {
01171                             #ifdef GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT
01172                                 glGetIntegerv (GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &NPOTDMaxTextureSize);
01173                                 if (NPOTDMaxTextureSize < pOpenGLCaps->maxNOPTDTextureSize)
01174                                     pOpenGLCaps->maxNOPTDTextureSize = NPOTDMaxTextureSize;
01175                             #endif
01176                             }
01177                         }
01178                         // next display
01179                         hgdNthDevice = GetNextDevice(hgdNthDevice);
01180                     }
01181             }
01182             aglDestroyContext( ctx );
01183         }
01184         else
01185         { // could not build context set caps to min
01186             pOpenGLCaps->f_ext_texture_rectangle = false;
01187             pOpenGLCaps->f_ext_client_storage = false;
01188             pOpenGLCaps->f_ext_packed_pixel = false;
01189             pOpenGLCaps->f_ext_texture_edge_clamp = false;
01190             pOpenGLCaps->f_gl_texture_edge_clamp = false;
01191             pOpenGLCaps->maxTextureSize = 0;
01192         }
01193         
01194         // set clamp param based on retrieved capabilities
01195         if (pOpenGLCaps->f_gl_texture_edge_clamp) // if OpenGL 1.2 or later and texture edge clamp is supported natively
01196                     pOpenGLCaps->edgeClampParam = GL_CLAMP_TO_EDGE;  // use 1.2+ constant to clamp texture coords so as to not sample the border color
01197         else if (pOpenGLCaps->f_ext_texture_edge_clamp) // if GL_SGIS_texture_edge_clamp extension supported
01198             pOpenGLCaps->edgeClampParam = GL_CLAMP_TO_EDGE_SGIS; // use extension to clamp texture coords so as to not sample the border color
01199         else
01200             pOpenGLCaps->edgeClampParam = GL_CLAMP; // clamp texture coords to [0, 1]
01201 
01202         aglDestroyPixelFormat( fmt );
01203         DisposeWindow( pWin );
01204     }
01205 }
01206 
01207 //--------------------------------------------------------------------------------------------
01208 
01209 static OSStatus
01210 WindowEventHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon )
01211 {
01212     OSStatus    err = eventNotHandledErr;
01213     WindowRef    window = (WindowRef) inRefcon;
01214 
01215     if( GetEventClass(inEvent) == kEventClassMouse )
01216     {
01217         Point mousePoint; // UInt32 modifiers;
01218         verify_noerr( GetEventParameter(inEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePoint) );
01219         pRecImage pWindowInfo = (pRecImage) GetWRefCon (window); // get the gl info for the window
01220         if(pWindowInfo) {
01221             SetPortWindowPort(window);
01222             GlobalToLocal (&mousePoint); //convert mouse coordinates to local coordintes prior to recording
01223             mousePoint.h /= pWindowInfo->zoomX; mousePoint.v /= pWindowInfo->zoomY;
01224             if(mousePoint.h >= 0 && mousePoint.h < pWindowInfo->imageWidth && mousePoint.v >= 0 && mousePoint.v < pWindowInfo->imageHeight)
01225                 g_video->on_mouse(mousePoint.h, mousePoint.v, GetEventKind(inEvent) == kEventMouseUp?-1:1), err = noErr;
01226         }
01227     }
01228     else if( GetEventClass(inEvent) == kEventClassKeyboard )
01229     {
01230         char ch;
01231         verify_noerr( GetEventParameter( inEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof( ch ), NULL, &ch ) );
01232         if(g_video)
01233             g_video->on_key(ch);
01234     }
01235     else //if( GetEventClass(inEvent) == kEventClassWindow )
01236     {
01237         if (GetEventKind(inEvent) == kEventWindowDrawContent)
01238         {
01239             //DrawGL(window);
01240             err = noErr;
01241         }
01242         else if (GetEventKind(inEvent) == kEventWindowClose)
01243         {
01244             if (window)
01245             {
01246                 g_video->running = false;
01247             }
01248             err = noErr;
01249         }
01250         else if (GetEventKind(inEvent) == kEventWindowShowing)
01251         {
01252             err = BuildGLForWindow (window);
01253         }
01254         else if ((GetEventKind(inEvent) == kEventWindowResizeCompleted) || (GetEventKind(inEvent) == kEventWindowDragCompleted))
01255         {
01256             err = ResizeMoveGLWindow (window);
01257         }
01258         else if (GetEventKind(inEvent) == kEventWindowZoomed)
01259         {
01260             err = ResizeMoveGLWindow (window);
01261         }
01262     }
01263     
01264     return err;
01265 }
01266 //--------------------------------------------------------------------------------------------
01267 DEFINE_ONE_SHOT_HANDLER_GETTER( WindowEventHandler )
01268 
01269 //--------------------------------------------------------------------------------------------
01270 WindowRef HandleNew()
01271 {
01272     OSStatus  err;
01273     WindowRef window;
01274     pRecImage pWindowInfo = NULL;
01275     static const EventTypeSpec    kWindowEvents[] =
01276     {
01277        { kEventClassMouse, kEventMouseUp },
01278        { kEventClassMouse, kEventMouseDown },
01279        { kEventClassKeyboard, kEventRawKeyDown },
01280 //       { kEventClassCommand, kEventCommandProcess },
01281        { kEventClassWindow, kEventWindowShowing },
01282        { kEventClassWindow, kEventWindowClose },
01283        { kEventClassWindow, kEventWindowDrawContent },
01284        { kEventClassWindow, kEventWindowResizeCompleted },
01285        { kEventClassWindow, kEventWindowDragCompleted },
01286        { kEventClassWindow, kEventWindowZoomed}
01287     };
01288     if (!gpOpenGLCaps)
01289     {
01290         gpOpenGLCaps = (pRecGLCap) NewPtrClear (sizeof (recGLCap));
01291         FindMinimumOpenGLCapabilities (gpOpenGLCaps);
01292     }
01293 
01294     // Create a window. "MainWindow" is the name of the window object. This name is set in 
01295     // InterfaceBuilder when the nib is created.
01296     err = CreateWindowFromNib( sNibRef, CFSTR("MainWindow"), &window );
01297     require_noerr( err, CantCreateWindow );
01298     // We don't need the nib reference anymore.
01299     DisposeNibReference(sNibRef);
01300     
01301     pWindowInfo = (recImage *) NewPtrClear (sizeof (recImage));
01302     pWindowInfo->textureWidth = pWindowInfo->imageWidth = g_sizex;
01303     pWindowInfo->textureHeight = pWindowInfo->imageHeight = g_sizey;
01304     pWindowInfo->imageDepth = 32;
01305     pWindowInfo->fTileTextures = true;
01306     pWindowInfo->fOverlapTextures = false; // TODO: ???
01307     pWindowInfo->maxTextureSize = gpOpenGLCaps->maxTextureSize;
01308     pWindowInfo->fNPOTTextures = gpOpenGLCaps->f_ext_texture_rectangle;
01309     pWindowInfo->fClientTextures = gpOpenGLCaps->f_ext_client_storage; // texture from client memory if available
01310     pWindowInfo->fAGPTexturing = false; // if AGP texturing selected
01311     pWindowInfo->pImageBuffer = (unsigned char*) g_pImg;
01312     // set default parameters for this image
01313     pWindowInfo->zoomX = 1.0f; // pixel 1 to 1 size
01314     pWindowInfo->zoomY = 1.0f; // pixel 1 to 1 size
01315     SetWRefCon (window, (long) pWindowInfo);
01316     char buffer[256]; buffer[0] = snprintf(buffer+1, 255, "%s", g_video->title);
01317     SetWTitle (window, (ConstStr255Param)buffer);
01318     // Install a command handler on the window. We don't use this handler yet, but nearly all
01319     // Carbon apps will need to handle commands, so this saves everyone a little typing.
01320     InstallStandardEventHandler(GetWindowEventTarget(window));
01321     InstallWindowEventHandler( window, GetWindowEventHandlerUPP(),
01322                                GetEventTypeCount( kWindowEvents ), kWindowEvents, window, NULL );
01323     if (noErr != BuildGLForWindow (window))
01324     {
01325         DisposeGLForWindow (window);
01326         DisposeWindow (window);
01327         return 0;
01328     }
01329 
01330     // Position new windows in a staggered arrangement on the main screen
01331     RepositionWindow( window, NULL, kWindowCascadeOnMainScreen );
01332     
01333     // The window was created hidden, so show it
01334     ShowWindow( window );
01335     return window;
01336   
01337 CantCreateWindow:
01338     return 0;
01339 }
01340 
01341 
01342 //--------------------------------------------------------------------------------------------
01343 static OSStatus
01344 AppEventHandler( EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon )
01345 {
01346     OSStatus    result = eventNotHandledErr;
01347 
01348     return result;
01349 }
01350 
01351 //=======================================================================================================
01352 
01353 video::video()
01354     : red_mask(0xff0000), red_shift(16), green_mask(0xff00),
01355       green_shift(8), blue_mask(0xff), blue_shift(0), depth(24)
01356 {
01357     assert(g_video == 0);
01358     g_video = this; title = "Video"; updating = true; calc_fps = false;
01359 }
01360 
01361 bool video::init_window(int x, int y)
01362 {
01363     g_sizex = x; g_sizey = y; g_window = 0;
01364     g_pImg = new unsigned int[x*y];
01365 
01366     // Check for graphics availability
01367     if( CGGetOnlineDisplayList(0, NULL, NULL) ) {
01368         running = true; // console mode
01369         return false;
01370     }
01371 
01372     OSStatus                    err;
01373     static const EventTypeSpec    kAppEvents[] =
01374     {
01375         { kEventClassCommand, kEventCommandProcess }
01376     };
01377 
01378     // Create a Nib reference, passing the name of the nib file (without the .nib extension).
01379     // CreateNibReference only searches into the application bundle.
01380     err = CreateNibReference( CFSTR("main"), &sNibRef );
01381     require_noerr( err, ReturnLabel );
01382 
01383     // Install our handler for common commands on the application target
01384     // Register for standard event handlers
01385     InstallStandardEventHandler(GetApplicationEventTarget()); // Doesn't work?
01386     verify_noerr( InstallApplicationEventHandler( NewEventHandlerUPP( AppEventHandler ),
01387                                     GetEventTypeCount( kAppEvents ), kAppEvents, 0, NULL ) );
01388     
01389     // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
01390     // object. This name is set in InterfaceBuilder when the nib is created.
01391     //err = SetMenuBarFromNib( sNibRef, CFSTR("MenuBar") );
01392     //require_noerr( err, ReturnLabel );
01393     InstallStandardEventHandler(GetMenuEventTarget(AcquireRootMenu()));
01394 
01395     // Create a new window. A full-fledged application would do this from an AppleEvent handler for kAEOpenApplication.
01396     g_window = HandleNew();
01397 
01398 ReturnLabel:
01399     return running = g_window != 0;
01400 }
01401 
01402 bool video::init_console()
01403 {
01404     running = true;
01405     return true;
01406 }
01407 
01408 void video::terminate()
01409 {
01410     g_video = 0; running = false;
01411     if(g_pImg) { delete[] g_pImg; g_pImg = 0; }
01412     if(g_window) {
01413         DisposeGLForWindow (g_window);
01414         DisposeWindow (g_window);
01415         g_window = 0;
01416     }
01417 }
01418 
01419 video::~video()
01420 {
01421     if(g_video) terminate();
01422 }
01423 
01425 bool video::next_frame()
01426 {
01427     if(!running) return false;
01428     if(!g_window) return running;
01430     if(threaded && pthread_mutex_trylock(&g_mutex))
01431         return running;
01432     g_fps++;
01433     struct timezone tz; struct timeval now_time; gettimeofday(&now_time, &tz);
01434     double sec = (now_time.tv_sec+1.0*now_time.tv_usec/1000000.0) - (g_time.tv_sec+1.0*g_time.tv_usec/1000000.0);
01435     if(sec > 1) {
01436         memcpy(&g_time, &now_time, sizeof(g_time));
01437         if(calc_fps) {
01438             double fps = g_fps; g_fps = 0;
01439             char buffer[256]; buffer[0] = snprintf(buffer+1, 255, "%s%s: %d fps", title, updating?"":" (no updating)", int(fps/sec));
01440             SetWTitle (g_window, (ConstStr255Param) buffer );
01441         }
01442       }
01443 
01444     EventRef theEvent;
01445     EventTargetRef theTarget;
01446     OSStatus                    err;
01447     // Run the event loop
01448 
01449     theTarget = GetEventDispatcherTarget();
01450     while( (err = ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &theEvent)) == noErr)
01451     {
01452         SendEventToEventTarget(theEvent, theTarget);
01453         ReleaseEvent(theEvent);
01454     }
01455     if(err != eventLoopTimedOutErr) running = false;
01456     if(updating) {
01457         pRecImage pWindowInfo = (pRecImage) GetWRefCon (g_window); // get the gl info for the window
01458         if(pWindowInfo) DrawGL(g_window);
01459     }
01460     if(threaded) pthread_mutex_unlock(&g_mutex);
01461     return true;
01462 }
01463 
01465 void video::main_loop()
01466 {
01467     struct timezone tz; gettimeofday(&g_time, &tz);
01468     //RunApplicationEventLoop(); -- using another application loop model
01469     on_process();
01470 }
01471 
01473 void video::show_title()
01474 {
01475     char buffer[256]; buffer[0] = snprintf(buffer+1, 255, "%s", title);
01476     SetWTitle (g_window, (ConstStr255Param) buffer );
01477 }
01478 
01480 
01481 drawing_area::drawing_area(int x, int y, int sizex, int sizey)
01482     : start_x(x), start_y(y), size_x(sizex), size_y(sizey), pixel_depth(24),
01483     base_index(y*g_sizex + x), max_index(g_sizex*g_sizey), index_stride(g_sizex), ptr32(g_pImg)
01484 {
01485     assert(x < g_sizex); assert(y < g_sizey);
01486     assert(x+sizex <= g_sizex); assert(y+sizey <= g_sizey);
01487 
01488     index = base_index; // current index
01489 }
01490 
01491 drawing_area::~drawing_area() {}

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net