Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phSDLImageWindow.cpp

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #if defined(HAVE_UNISTD_H)
00031     #include <unistd.h>
00032 #endif
00033 
00034 #include <phStandard.h>
00035 #include <ImageUtil.h>
00036 
00037 #include <phSDLImageWindow.h>
00038 
00039 #include <SDL.h>
00040 #include <SDL_thread.h>
00041 
00042 #include <phError.h>
00043 #include <phMemory.h>
00044 #include <phPrint.h>
00045 
00046 /* ---------------------------------------------------------------------- */
00047 struct phSDLWindowInfo_t
00048 {
00049     Uint32          m_init_flags;
00050         
00051     SDL_Rect        m_screen_rect;
00052     SDL_Surface    *m_screen_surface;
00053     
00054     SDL_Rect        m_image_rect;
00055     SDL_Surface    *m_image_surface;
00056 
00057     int             m_fullscreen;
00058     SDL_Rect        m_fullscreen_rect;
00059     SDL_Rect        m_windowed_rect;
00060    
00061     SDL_Color       m_grayscale_colors[256];
00062 };
00063 
00064 /* ---------------------------------------------------------------------- */
00065 /* display/sdl/phSDLImageWindow.cpp
00066  *
00067  * SDLDisplay : cross platform fast image displaying utility
00068  *      (cross platform except possibly the phImage class)
00069  *
00070  * This file has the C-ish routines for the SDL threads and SDL
00071  * interface code.
00072  *
00073  * ---------------------------------------------------------------------- */
00074 /* ---------------------------------------------------------------------- */
00075 #if phDONT_PRINT_ERRORS
00076     #define phSDL_ERR_PRINT(fmt, ...)
00077 #elif phNO_FUNCTION_VARIABLE
00078     #define phSDL_ERR_PRINT(fmt, ...) \
00079     { \
00080         fprintf(stderr, \
00081                 "(pid:%d %s:%d)\t*** ERROR *** " fmt ": %s\n", \
00082                 getpid(),__FILE__, __LINE__, \
00083                 ## __VA_ARGS__, SDL_GetError()); \
00084         fflush(stderr); \
00085     }
00086 #else
00087     #define phSDL_ERR_PRINT(fmt, ...) \
00088     { \
00089         fprintf(stderr, \
00090                 "(pid:%d %s:%d @ %s)\t*** ERROR *** " fmt ": %s\n", \
00091                 getpid(),__FILE__, __LINE__, function, \
00092                 ## __VA_ARGS__, SDL_GetError()); \
00093         fflush(stderr); \
00094     }
00095 #endif
00096 
00097 /* ---------------------------------------------------------------------- */
00098 #define phSDL_CHECK_NULLPTR(ptr,fmt, ...)                        \
00099 { \
00100     if (ptr == NULL) {\
00101         phSDL_ERR_PRINT(fmt,##__VA_ARGS__);\
00102     }\
00103 }
00104 /* ---------------------------------------------------------------------- */
00105 #define phSDL_RC(rc,action, ...) \
00106     { \
00107         if (rc < 0) \
00108         { \
00109             phSDL_ERR_PRINT( __VA_ARGS__ ); \
00110             action; \
00111         } \
00112     }
00113 #define SDL_CHECK_RC(rc, ...)  phSDL_RC(rc,  goto error, __VA_ARGS__ );
00114 #define SDL_BREAK_RC(rc, ...)  phSDL_RC(rc,  break, __VA_ARGS__ );
00115 #define SDL_CONT_RC(rc, ...)   phSDL_RC(rc,  continue, __VA_ARGS__ );
00116 #define SDL_PRINT_RC(rc, ...)  phSDL_RC(rc,  , __VA_ARGS__ );
00117 
00118 /* ---------------------------------------------------------------------- */
00119 #define SDL_USER_THREAD_WAKEUP (SDL_USEREVENT + 0)
00120 
00121 /* ----------------------------------------------------------------------------
00122  * ------------------------------------------------------------------------- */
00123 
00124 #define LOCK_SURFACE(s)                 \
00125         if (SDL_MUSTLOCK(s))            \
00126         { \
00127             if (SDL_LockSurface(s) == -1)   \
00128             { \
00129                 SDL_PRINT_RC(-1,"SDL_LockSurface failed."); \
00130             } \
00131         }
00132 
00133 #define UNLOCK_SURFACE(s)               \
00134         if (SDL_MUSTLOCK(s)) SDL_UnlockSurface(s);  
00135 
00136 #define SDL_MIN_WIDTH 20
00137 #define SDL_MIN_HEIGHT 20
00138 
00139 /* ---------------------------------------------------------------------- */
00140 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00141 
00142 #if __BYTE_ORDER != __BIG_ENDIAN
00143 #error "SDL_BYTEORDER Knows something about endianness that we don\'t : BIG"
00144 #endif
00145 
00146 #else /* Little Endian */
00147 
00148 #if __BYTE_ORDER != __LITTLE_ENDIAN
00149 #error "SDL_BYTEORDER Knows something about endianness that we don\'t : LITTLE"
00150 #endif
00151 
00152 #endif
00153       
00154 /* ------------------------------------------------------------------------- */
00155 int EventFilter(const SDL_Event *event)
00156 {
00157     switch(event->type)
00158     {
00159         case SDL_ACTIVEEVENT:
00160         case SDL_VIDEORESIZE:
00161         case SDL_VIDEOEXPOSE:
00162         case SDL_QUIT:
00163         case SDL_KEYDOWN:
00164         case SDL_KEYUP:
00165         case SDL_SYSWMEVENT:
00166             return 1;
00167             
00168         case SDL_USEREVENT:
00169             if (event->user.code == 0)
00170                 return 0;
00171             else
00172                 return 1;
00173 
00174         case SDL_MOUSEMOTION:
00175         case SDL_MOUSEBUTTONDOWN:
00176         case SDL_MOUSEBUTTONUP:
00177         case SDL_JOYAXISMOTION:
00178         case SDL_JOYBALLMOTION:
00179         case SDL_JOYHATMOTION:
00180         case SDL_JOYBUTTONDOWN:
00181         case SDL_JOYBUTTONUP:
00182             return 0;
00183     }
00184     return 0;
00185 }
00186 
00187 /* ------------------------------------------------------------------------- */
00188 phSDLImageWindow::phSDLImageWindow( uint32_t x, uint32_t y,
00189                                     uint32_t w, uint32_t h,
00190                                     char *title,
00191                                     uint32_t flags ) :
00192                 phImageWindow(x,y,w,h,title,flags )
00193 {
00194     phFUNCTION("phSDLImageWindow::phSDLImageWindow")
00195     
00196     uint32_t i          = 0;
00197     /*uint32_t title_len  = (title != NULL) ? strlen(title) + 20 : 50;*/
00198 
00199     rc = this->lock();
00200     phPRINT_RC(rc,NULL,"this->lock()");
00201 
00202     this->m_info = (phSDLWindowInfo_t *)phCalloc(1,
00203                         sizeof(phSDLWindowInfo_t));
00204     phPRINT_NULLPTR(this->m_info,NULL,
00205             "phCalloc failed to allocate phSDLWindowInfo");
00206     
00207     this->m_currentDepth    = 0;
00208     this->m_currentFormat   = phImageNOFORMAT;
00209     
00210     this->m_info->m_init_flags = SDL_INIT_VIDEO | 
00211                                  SDL_INIT_NOPARACHUTE | 
00212                                  SDL_INIT_EVENTTHREAD;
00213 
00214     phMemset(&this->m_info->m_screen_rect,     0,sizeof(SDL_Rect));
00215     phMemset(&this->m_info->m_windowed_rect,   0,sizeof(SDL_Rect));
00216     phMemset(&this->m_info->m_fullscreen_rect, 0,sizeof(SDL_Rect));
00217     
00218     this->m_info->m_fullscreen      = 0;
00219     this->m_info->m_screen_surface  = NULL;
00220     this->m_info->m_image_surface   = NULL;
00221     this->m_info->m_image_rect.x    = 
00222     this->m_info->m_image_rect.y    = 0;
00223     this->m_info->m_image_rect.w    = w;
00224     this->m_info->m_image_rect.h    = h;
00225 
00226     this->setName("phSDLImageWindow");
00227     
00228     if (this->m_title == NULL)
00229     {
00230         this->setTitle("Phission: phSDLImageWindow");
00231     }
00232 
00233     this->m_formats = phSDLImageWindow_ValidFormats;
00234     
00235     for (i = 0; i < 256; i++) {
00236         this->m_info->m_grayscale_colors[i].r = 
00237         this->m_info->m_grayscale_colors[i].g = 
00238         this->m_info->m_grayscale_colors[i].b = i;
00239     }
00240     
00241 /*error:*/
00242     rc = this->unlock();
00243     phPRINT_RC(rc,NULL,"this->unlock() failed.");
00244 
00245     return;
00246 }
00247 
00248 /* ------------------------------------------------------------------------- */
00249 phSDLImageWindow::~phSDLImageWindow()
00250 {
00251     phFUNCTION("phSDLImageWindow::~phSDLImageWindow")
00252 
00253     rc = this->lock();
00254     phPRINT_RC(rc,NULL,"this->lock();");
00255     
00256     if (this->m_info->m_image_surface) 
00257     {
00258         SDL_FreeSurface(this->m_info->m_image_surface);
00259     }
00260 
00261     phFree(this->m_info);
00262 }
00263 
00264 /* ----------------------------------------------------------------------------
00265  * image_window_init -- initialize the buffer surface; buffer is drawn to
00266  * ------------------------------------------------------------------------- */
00267 int phSDLImageWindow::image_window_init()
00268 {
00269     phFUNCTION("phSDLImageWindow::image_window_init")
00270     uint32_t    depth       = 0;
00271     int         locked      = 0;
00272     int         readLocked  = 0;
00273     uint32_t    format      = phImageNOFORMAT;
00274     char        *whichone   = "unknown";
00275         
00276     rc = this->lock();
00277     phCHECK_RC(rc,NULL,"this->lock()");
00278     locked = 1;
00279 
00280     this->m_info->m_image_rect.w = this->m_info->m_screen_rect.w;
00281     this->m_info->m_image_rect.h = this->m_info->m_screen_rect.h;
00282     
00283     if (this->m_info->m_image_surface) {
00284         SDL_FreeSurface(this->m_info->m_image_surface);
00285     }
00286 
00287     rc = this->m_image.readLock();
00288     phCHECK_RC(rc,NULL,"this->m_image.readLock() failed.");
00289     readLocked = 1;
00290 
00291     format = this->m_image.getFormat();
00292 
00293     if (format & (phSDLImageWindow_ValidFormats))
00294     {
00295         switch (format)
00296         {
00297             case phImageRGB24:
00298             case phImageBGR24:
00299                 depth = 24;
00300                 break;
00301             case phImageABGR32:
00302             case phImageRGBA32:
00303             case phImageBGRA32:
00304                 depth = 32;
00305                 break;
00306             case phImageGREY8:
00307                 depth = 8;
00308                 break;
00309         }
00310 /*
00311         phPROGRESS("%s - 0x%08x:0x%08x:0x%08x:0x%08x\n",
00312                 phImageFormatToString(format),
00313                 phImageFormatTo32BitMask(format,phCHANNEL_RED),
00314                 phImageFormatTo32BitMask(format,phCHANNEL_GREEN),
00315                 phImageFormatTo32BitMask(format,phCHANNEL_BLUE),
00316                 phImageFormatTo32BitMask(format,phCHANNEL_ALPHA) );
00317 */
00318         if (depth > 8)
00319         {
00320             whichone = "depth > 8";
00321             this->m_info->m_image_surface = 
00322                 SDL_CreateRGBSurface(SDL_HWSURFACE,
00323                     this->m_info->m_image_rect.w,
00324                     this->m_info->m_image_rect.h, 
00325                     depth,
00326                     phImageFormatTo32BitMask(format,phCHANNEL_RED),
00327                     phImageFormatTo32BitMask(format,phCHANNEL_GREEN),
00328                     phImageFormatTo32BitMask(format,phCHANNEL_BLUE),
00329                     phImageFormatTo32BitMask(format,phCHANNEL_ALPHA) );
00330             
00331         }
00332         else if (depth > 0)
00333         {
00334             whichone = "0 < depth <= 8";
00335             this->m_info->m_image_surface = 
00336                 SDL_CreateRGBSurface(SDL_SWSURFACE,
00337                     this->m_info->m_image_rect.w,
00338                     this->m_info->m_image_rect.h, 
00339                     depth, 0,0,0,0);
00340 
00341             rc  = SDL_SetColors(this->m_info->m_image_surface, 
00342                                 this->m_info->m_grayscale_colors, 0, 256);
00343             SDL_PRINT_RC(rc,"SDL_SetColors");
00344         }
00345         else
00346         {
00347             whichone = "depth == 0";
00348             this->m_info->m_image_surface = NULL;
00349         }
00350         //phPROGRESS("%s\n",whichone);
00351         phSDL_CHECK_NULLPTR( this->m_info->m_image_surface, 
00352                              "SDL_CreateRGBSurface(%s) failed",
00353                              whichone );
00354     
00355         /* set up the blit coordinates for the image */
00356         this->m_info->m_image_rect.x = 0;
00357         this->m_info->m_image_rect.y = 0;
00358     }
00359     
00360     if (depth != 0)
00361     {
00362         this->m_currentDepth = depth;
00363     }
00364     
00365     if (format != (uint32_t)phImageNOFORMAT)
00366     {
00367         //phPROGRESS("New Format: %s\n",
00368         //         phImageFormatToString(format));
00369         this->m_currentFormat = format;
00370     }
00371 
00372     rc = this->m_image.rwUnlock();
00373     readLocked = 0;
00374     phCHECK_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00375 
00376     rc = this->unlock();
00377     locked = 0;
00378     phCHECK_RC(rc,NULL,"this->unlock() failed.");
00379 
00380     return phSUCCESS;
00381 
00382 error:
00383     if (readLocked)
00384     {
00385         rc = this->m_image.rwUnlock();
00386         readLocked = 0;
00387         //phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00388     }
00389 
00390     if (locked)
00391     {
00392         rc = this->unlock();
00393         phPRINT_RC(rc,NULL,"this->unlock() failed.");
00394     }
00395 
00396     return phFAIL;
00397 }
00398 
00399 /* ----------------------------------------------------------------------------
00400  * window_init -- initialize the screen and image surfaces
00401  * ------------------------------------------------------------------------- */
00402 int phSDLImageWindow::window_init(  uint32_t x,
00403                                     uint32_t y,
00404                                     uint32_t w, 
00405                                     uint32_t h )
00406 {
00407     phFUNCTION("phSDLImageWindow::window_init")
00408 
00409     uint32_t flags = 0;
00410 
00411     /* create the "screen," a WIDTHxHEIGHT window.
00412      * passing "0" for bit depth means SDL will pick the best available,
00413      * usually 32 bits-per-pixel.  the SDL_SWSURFACE flag means create the
00414      * screen surface in system memory.  Always use SDL_DOUBLEBUF, it makes
00415      * for smooth video
00416      */
00417     rc = this->lock();
00418     phPRINT_RC(rc,NULL,"this->lock()");
00419 
00420     flags = SDL_HWSURFACE | 
00421         ((this->m_info->m_fullscreen) ? SDL_FULLSCREEN : SDL_RESIZABLE ) | 
00422         SDL_DOUBLEBUF;
00423     
00424     if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
00425     {
00426         SDL_Rect **modes = SDL_ListModes(NULL,flags);
00427     
00428         this->m_info->m_fullscreen_rect.w = w;
00429         this->m_info->m_fullscreen_rect.h = h;
00430 
00431         if ((modes != (SDL_Rect **)0) && 
00432             (modes != (SDL_Rect **)-1))
00433         {
00434             int i = 0;
00435             int neww = 0;
00436             int newh = 0;
00437             for (i = 0; modes[i]; ++i)
00438             {
00439                 if (modes[i]->w > neww)
00440                 {
00441                     neww = modes[i]->w;
00442                     newh = modes[i]->h;
00443                 }
00444             }
00445             if ((neww != 0) && (newh != 0))
00446             {
00447                 this->m_info->m_fullscreen_rect.w = neww;
00448                 this->m_info->m_fullscreen_rect.h = newh;
00449             }
00450         }
00451 #if 0 
00452         if (this->m_info->m_fullscreen_rect.w < this->m_min_width) 
00453             this->m_info->m_fullscreen_rect.w = this->m_min_width;
00454         if (this->m_info->m_fullscreen_rect.h < this->m_min_height) 
00455             this->m_info->m_fullscreen_rect.w = this->m_min_height;
00456 #endif
00457         this->m_info->m_screen_rect = this->m_info->m_fullscreen_rect;
00458         SDL_ShowCursor(SDL_DISABLE);
00459     }
00460     else
00461     {
00462         if ((w == this->m_info->m_fullscreen_rect.w) && 
00463             (h == this->m_info->m_fullscreen_rect.h))
00464         {
00465             this->m_info->m_fullscreen_rect.w = 0;
00466             this->m_info->m_fullscreen_rect.h = 0;
00467             SDL_ShowCursor(SDL_ENABLE);
00468         }
00469         else
00470         {
00471             this->m_info->m_windowed_rect.w = w;
00472             this->m_info->m_windowed_rect.h = h;
00473         }
00474 
00475         if (this->m_info->m_windowed_rect.w < SDL_MIN_WIDTH) 
00476             this->m_info->m_windowed_rect.w = SDL_MIN_WIDTH;
00477         if (this->m_info->m_windowed_rect.h < SDL_MIN_HEIGHT) 
00478             this->m_info->m_windowed_rect.h = SDL_MIN_HEIGHT;
00479 
00480         this->m_info->m_screen_rect = this->m_info->m_windowed_rect;
00481         this->m_info->m_screen_rect.x = x;
00482         this->m_info->m_screen_rect.y = y;
00483     }
00484     this->m_w = this->m_info->m_screen_rect.w;
00485     this->m_h = this->m_info->m_screen_rect.h;
00486     this->m_info->m_screen_surface = 
00487             SDL_SetVideoMode(this->m_info->m_screen_rect.w,  /* width */
00488                              this->m_info->m_screen_rect.h,  /* height */
00489                              32,  /* bit depth */
00490                              flags );
00491     phSDL_CHECK_NULLPTR( this->m_info->m_screen_surface, 
00492                          "SDL_SetVideoMode() failed");
00493     /* set the title bar text */
00494     if (this->m_title == NULL)
00495     {
00496         SDL_WM_SetCaption("display","display");
00497     }
00498     else
00499         SDL_WM_SetCaption(this->m_title,this->m_title);
00500 
00501     rc = this->image_window_init();
00502     phCHECK_RC(rc,NULL,"image_window_init failed.");
00503 
00504     rc = this->unlock();
00505     phPRINT_RC(rc,NULL,"this->unlock() failed.");
00506 
00507     return phSUCCESS;
00508 
00509 error:
00510     rc = this->unlock();
00511     phPRINT_RC(rc,NULL,"this->unlock() failed.");
00512 
00513     return phFAIL;
00514 }
00515 /* ---------------------------------------------------------------------- */
00516 int phSDLImageWindow::private_hide()
00517 {
00518     /* 
00519      * We are locked when we get into a "private" method; Locking is done 
00520      * as a policy in any public interface method that calls a private 
00521      * (implementation specific) method 
00522     int locked = 1;
00523      */
00524     return phSUCCESS;
00525 }
00526 
00527 /* ---------------------------------------------------------------------- */
00528 int phSDLImageWindow::private_show()
00529 {
00530     /* 
00531      * We are locked when we get into a "private" method; Locking is done 
00532      * as a policy in any public interface method that calls a private 
00533      * (implementation specific) method 
00534     int locked = 1;
00535      */
00536     return phSUCCESS;
00537 }
00538 
00539 /* ------------------------------------------------------------------------- */
00540 int phSDLImageWindow::private_redraw()
00541 {
00542     phFUNCTION("phSDLImageWindow::private_redraw")
00543     uint32_t    new_depth    = 0;
00544     uint32_t    new_format   = phImageNOFORMAT;
00545     int         writeLocked = 0;
00546     /* 
00547      * We are locked when we get into a "private" method; Locking is done 
00548      * as a policy in any public interface method that calls a private 
00549      * (implementation specific) method 
00550     int locked = 1;
00551      */
00552     
00553     rc = this->m_image.writeLock();
00554     phCHECK_RC(rc, NULL, "this->m_image.writeLock() failed");
00555     writeLocked = 1;
00556     
00557     if ((!this->m_image.isNull()) && (SDL_GetAppState() & SDL_APPACTIVE))
00558     {
00559         rc = this->m_image.convert(this->getFormats());
00560         phPRINT_RC(rc,NULL,"m_image.convert() failed");
00561 
00562         new_format = this->m_image.getFormat();
00563         
00564         /* new_depth or new_format used to not accept a format type */
00565         switch (new_format)
00566         {
00567             case phImageRGB24:
00568             case phImageBGR24:
00569                 new_depth = 24;
00570                 break;
00571             case phImageABGR32:
00572             case phImageRGBA32:
00573             case phImageBGRA32:
00574                 new_depth = 32;
00575                 break;
00576             case phImageGREY8:
00577                 new_depth = 8;
00578                 break;
00579             default:
00580                 new_depth  = 0;
00581                 new_format = phImageNOFORMAT;
00582         }
00583 
00584         if (((new_depth  != this->m_currentDepth) && 
00585              (new_depth != 0)) 
00586             ||
00587             ((new_format != this->m_currentFormat) && 
00588              (new_format != (uint32_t)phImageNOFORMAT)))
00589         {
00590             rc = this->image_window_init();
00591             phPRINT_RC(rc,NULL,"image_window_init() failed.");
00592         }
00593         if ((new_depth != 0) && (new_format != (uint32_t)phImageNOFORMAT))
00594         {
00595             /* maintain frames-per-second */
00596             this->tickFrame();
00597 
00598             if ((this->m_info->m_image_surface) && 
00599                 (this->m_info->m_screen_surface))
00600             {
00601                 LOCK_SURFACE(this->m_info->m_image_surface);
00602                 this->m_image.resize(this->m_info->m_image_surface->w,
00603                         this->m_info->m_image_surface->h);
00604                 memcpy( (void *)this->m_info->m_image_surface->pixels,
00605                         (void *)this->m_image.getData(),
00606                         this->m_image.getSize());
00607                 UNLOCK_SURFACE(this->m_info->m_image_surface);
00608                 
00609                 /* now copy the image back to the screen for display */
00610                 SDL_BlitSurface(this->m_info->m_image_surface, 
00611                         NULL, 
00612                         this->m_info->m_screen_surface, 
00613                         &(this->m_info->m_image_rect));
00614                 SDL_Flip(this->m_info->m_screen_surface);
00615             }
00616         }
00617     }
00618     
00619     /* unlock the mutexes */
00620     rc = this->m_image.rwUnlock();
00621     writeLocked = 0;
00622     phCHECK_RC(rc,NULL, "this->m_image.rwUnlock() failed");
00623     
00624     return phSUCCESS;
00625 error:
00626     if (writeLocked)
00627     {
00628         rc = this->m_image.rwUnlock();
00629         phPRINT_RC(rc,NULL, "this->m_image.rwUnlock() failed");
00630         writeLocked = 0;
00631     }
00632     
00633     return phFAIL;
00634 }
00635 
00636 /* ------------------------------------------------------------------------- */
00637 int phSDLImageWindow::private_update()
00638 {
00639     phFUNCTION("phSDLImageWindow::private_update")
00640     int writeLocked = 0;
00641     /* 
00642      * We are locked when we get into a "private" method; Locking is done 
00643      * as a policy in any public interface method that calls a private 
00644      * (implementation specific) method 
00645     int locked = 1;
00646      */
00647 
00648     rc = this->m_image.writeLock();
00649     phCHECK_RC(rc,NULL,"this->m_image.writeLock()");
00650     writeLocked = 1;
00651     
00652     if (this->m_image.isNull() == 0)
00653     {
00654         rc = this->private_redraw();
00655         phPRINT_RC(rc,NULL,"this->private_redraw() failed.");
00656     }
00657     
00658     rc = this->m_image.rwUnlock();
00659     writeLocked = 0;
00660     phCHECK_RC(rc,NULL,"this->m_image.rwUnlock()");
00661             
00662     return phSUCCESS;
00663 error:
00664     if (writeLocked)
00665     {
00666         rc = this->m_image.rwUnlock();
00667         phPRINT_RC(rc,NULL,"this->m_image.rwUnlock()");
00668         writeLocked = 0;
00669     }
00670     
00671     return phFAIL;
00672 }
00673 
00674 /* ------------------------------------------------------------------------- */
00675 /* this method is used to calculate the mapping from the requested resize 
00676  * dims to the actual implementable resize values. */
00677 /* ------------------------------------------------------------------------- */
00678 int phSDLImageWindow::calc_resize(uint32_t w,uint32_t h,
00679                                   uint32_t *tw, uint32_t *th )
00680 {
00681     phFUNCTION("phSDLImageWindow::calc_width_resize")
00682     uint32_t    step    = 0;
00683     uint32_t    ow      = w;
00684     uint32_t    oh      = h;
00685     int         retrc   = phSUCCESS;
00686 
00687     rc = this->lock();
00688     phPRINT_RC(rc,NULL,"this->lock()");
00689     
00690     step = (this->m_currentDepth / 8) + 1;
00691     
00692     /* Make sure the image can't be made smaller than
00693      * the original, it's just pointless to waste
00694      * CPU time making an image smaller when it's faster
00695      * to just blit it to memeory */
00696     if ((uint32_t)w < this->m_min_width) w = this->m_min_width;
00697     if ((uint32_t)h < this->m_min_height)h = this->m_min_height;
00698     
00699     /* For some reason, this has to be done to make sure the
00700      * scaling works */
00701     if (w % step) w += step - (w % step);
00702     if (h % step) h += step - (h % step);
00703     
00704     if ((uint32_t)w < this->m_min_width)  w = this->m_min_width;
00705     if ((uint32_t)h < this->m_min_height) h = this->m_min_height;
00706 
00707     *tw = w;
00708     *th = h;
00709 
00710     if ((w != ow) || (h != oh)) retrc = 1;
00711     
00712     rc = this->unlock();
00713     phPRINT_RC(rc,NULL,"this->unlock() failed.");
00714 
00715     return retrc;
00716 }
00717 
00718 /* ------------------------------------------------------------------------- */
00719 int phSDLImageWindow::private_resize(uint32_t w, uint32_t h)
00720 {
00721     phFUNCTION("phSDLImageWindow::private_resize")
00722     int writeLocked = 0;
00723     /* 
00724      * We are locked when we get into a "private" method; Locking is done 
00725      * as a policy in any public interface method that calls a private 
00726      * (implementation specific) method 
00727     int locked = 1;
00728      */
00729 
00730     rc = this->m_image.writeLock();
00731     phCHECK_RC(rc,NULL,"this->m_image.writeLock() failed.");
00732     writeLocked = 1;
00733 
00734     rc = this->calc_resize(w,h,&w,&h);
00735     phPRINT_RC(rc,NULL,"this->calc_resize() failed.");
00736     
00737     if ((w != this->getWidth()) ||
00738         (h != this->getHeight())|| 
00739         (rc == 1))
00740     {
00741         /* in between the update call in the Display Interface,
00742            (which will potentially have an invalid format) 
00743            and the actual call to 'update', this could potentially
00744            be called and the format could be unsupported. 
00745            Should we convert it? 
00746          */
00747         if (!this->m_image.isNull())
00748         {   
00749             rc = this->m_image.convert(this->getFormats());
00750             phPRINT_RC(rc,NULL,"m_image.convert() failed");
00751         }
00752         rc = this->window_init(this->m_info->m_screen_rect.x, 
00753                                 this->m_info->m_screen_rect.y,
00754                                 w, h);
00755         phCHECK_RC(rc,NULL,"this->window_init failed");
00756     
00757         rc = this->private_redraw();
00758         phCHECK_RC(rc,NULL,"private_redraw() failed.");
00759     }
00760                     
00761     rc = this->m_image.rwUnlock();
00762     writeLocked = 0;
00763     phCHECK_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00764 
00765     return phSUCCESS;
00766 error:
00767     
00768     if (writeLocked)
00769     {
00770         rc = this->m_image.rwUnlock();
00771         phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed.");
00772         writeLocked = 0;
00773     }
00774 
00775     return phFAIL;
00776 }
00777 
00778 /* ---------------------------------------------------------------------- */
00779 int phSDLImageWindow::private_move( int32_t x, int32_t y )
00780 {
00781     /* 
00782      * We are locked when we get into a "private" method; Locking is done 
00783      * as a policy in any public interface method that calls a private 
00784      * (implementation specific) method 
00785     int locked = 1;
00786      */
00787     return phSUCCESS;
00788 }
00789 
00790 /* ---------------------------------------------------------------------- */
00791 int phSDLImageWindow::private_minsize( uint32_t min_w, uint32_t min_h)
00792 {
00793     /* 
00794      * We are locked when we get into a "private" method; Locking is done 
00795      * as a policy in any public interface method that calls a private 
00796      * (implementation specific) method 
00797     int locked = 1;
00798      */
00799     return phSUCCESS;
00800 }    
00801 
00802 
00803 /* ---------------------------------------------------------------------- */
00804 int phSDLImageWindow::wakeup()
00805 {
00806     phFUNCTION("phSDLImageWindow::wakeup")
00807     
00808     int         retrc           = phSUCCESS;
00809     SDL_Event   wakeup_event;
00810     uint32_t    tries           = 0;
00811     uint32_t    max_tries       = 1000;
00812     
00813     /* Setup the wakeup event */
00814     wakeup_event.type = SDL_USER_THREAD_WAKEUP;
00815     wakeup_event.user.code = 1; /* Must be 1 to prevent filtering */
00816 
00817     do
00818     {
00819         rc = SDL_PushEvent(&wakeup_event);
00820     }
00821     while ((rc == -1) && (tries++ < max_tries));
00822     
00823     if (rc == -1)
00824     {
00825         phPRINT_RC(rc,NULL,"SDL_PushEvent failed to post wakeup_event");
00826         retrc = phFAIL;
00827     }
00828     else
00829     {
00830         retrc = phSUCCESS;
00831     }
00832 
00833     this->m_image.wakeup_self();
00834    
00835 //    rc = this->phImageWindow::wakeup();
00836     phPRINT_RC(rc,NULL,"this->phImageWindow::wakeup()");
00837     
00838     return retrc;
00839 }
00840 
00841 /* ---------------------------------------------------------------------- */
00842 int phSDLImageWindow::cleanup()
00843 {
00844     /* stop SDL */
00845     SDL_Quit();
00846 
00847     return phSUCCESS;
00848 }
00849 
00850 /* ---------------------------------------------------------------------- */
00851 int phSDLImageWindow::run()
00852 {
00853     phFUNCTION("phSDLImageWindow::run")
00854     
00855     int visible     = 0;
00856     int redraw      = 0;
00857     int sdl_started = 0;
00858     
00859     SDL_Event event;            /* event object */
00860 
00861     short keysymdown[SDLK_LAST];
00862     memset(keysymdown,0,sizeof(keysymdown));
00863 
00864     DEBUG_PRINT("Thread started\n");
00865    
00866     /* start SDL */
00867     /* initialize the SDL subsystem */
00868     rc = SDL_Init(this->m_info->m_init_flags);
00869     SDL_CHECK_RC(rc, "SDL_Init() failed");
00870     sdl_started = 1;
00871     
00872     /* Filter out unused events */
00873     SDL_SetEventFilter(EventFilter);
00874     SDL_EventState(SDL_MOUSEMOTION,SDL_IGNORE);
00875     SDL_EventState(SDL_MOUSEBUTTONDOWN,SDL_IGNORE);
00876     SDL_EventState(SDL_MOUSEBUTTONUP,SDL_IGNORE);
00877     SDL_EventState(SDL_JOYAXISMOTION,SDL_IGNORE);
00878     SDL_EventState(SDL_JOYBALLMOTION,SDL_IGNORE);
00879     SDL_EventState(SDL_JOYHATMOTION,SDL_IGNORE);
00880     SDL_EventState(SDL_JOYBUTTONDOWN,SDL_IGNORE);
00881     SDL_EventState(SDL_JOYBUTTONUP,SDL_IGNORE);
00882     
00883     /* initialize the display */
00884     rc = this->window_init(this->m_x,this->m_y,this->m_w,this->m_h);
00885     phCHECK_RC(rc,NULL, "window_init() failed");
00886 
00887     /* int SDL_EnableKeyRepeat(int delay, int interval);*/
00888     /*  SDL_DEFAULT_REPEAT_DELAY and SDL_DEFAULT_REPEAT_INTERVAL */
00889     rc = SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
00890                              SDL_DEFAULT_REPEAT_INTERVAL);
00891     SDL_CHECK_RC(rc,"SDL_EnableKeyRepeat");
00892 
00893     rc = this->signal_running();
00894     phCHECK_RC(rc,NULL,"this->signal_running()");
00895     
00896     while (this->isRunning())
00897     {
00898         if (SDL_WaitEvent(&event) == 1)
00899         {
00900             switch (event.type) {
00901                 /* Used to clean up blocking event thread */
00902                 case SDL_USER_THREAD_WAKEUP:
00903                     break;
00904                     
00905                 case SDL_QUIT: /* user closed the window */
00906                     this->setRunning(0);
00907                     this->m_image.wakeup_self();
00908                     break;
00909 
00910                 case SDL_KEYDOWN:  /* user hit escape */
00911                     if (keysymdown[event.key.keysym.sym] < 2)
00912                         keysymdown[event.key.keysym.sym]++;
00913 
00914                     break;
00915 
00916                 case SDL_KEYUP:
00917                     keysymdown[event.key.keysym.sym] = 0;
00918                     break;
00919 
00920                 case SDL_VIDEORESIZE:  /* resize the window */
00921                     {
00922                         uint32_t w = event.resize.w;
00923                         uint32_t h = event.resize.h;
00924 
00925                         rc = this->lock();
00926                         phPRINT_RC(rc,NULL,"this->lock() failed.");
00927     
00928                         /* The m_w and m_h members will be set 
00929                            through this call */
00930                         rc = this->private_resize(w,h);
00931                         phPRINT_RC(rc,NULL,"this->private_resize() failed.");
00932                         
00933                         rc = this->unlock();
00934                         phPRINT_RC(rc,NULL,"this->unlock() failed.");
00935                     }
00936                     break;
00937                     
00938                 case SDL_VIDEOEXPOSE: 
00939                     redraw = 1;
00940                     break;
00941                 
00942                 case SDL_ACTIVEEVENT: 
00943                     if (event.active.state == SDL_APPACTIVE)
00944                     {
00945                         DEBUG_PRINT("if (event.active.state == SDL_APPACTIVE)");
00946                         if ((visible != event.active.gain) &&
00947                             (visible == 0))
00948                         {
00949                             redraw = 1;
00950                         }
00951 
00952                         visible = event.active.gain; 
00953                     }                   
00954                     break;
00955             }
00956                 
00957             if (keysymdown[SDLK_ESCAPE] || keysymdown[SDLK_q]) 
00958             {
00959                 this->setRunning(0);
00960                 this->m_image.wakeup_self();
00961             }
00962 
00963             if ((redraw) && (visible))
00964             {
00965                 redraw = 0;
00966                 rc = this->lock();
00967                 phPRINT_RC(rc,NULL,"this->lock() failed.");
00968                 
00969                 rc = this->private_redraw();
00970                 phPRINT_RC(rc,NULL,"this->private_resize() failed.");
00971                 
00972                 rc = this->unlock();
00973                 phPRINT_RC(rc,NULL,"this->unlock() failed.");
00974             }
00975         }
00976     }
00977 
00978     DEBUG_PRINT("Thread returning cleanly\n");
00979  
00980    
00981     return phSUCCESS;
00982 error:
00983     phPROGRESS("Thread returning with error\n");
00984 
00985     if (sdl_started == 1)
00986     {
00987         /* stop SDL */
00988         SDL_Quit();
00989     }
00990     rc = this->signal_error();
00991     phPRINT_RC(rc,NULL,"this->signal_error()");
00992  
00993     return phFAIL;
00994 }
00995 
00996 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:03 2007 for phission by  doxygen 1.4.4