home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / wps / graphic / fractint / sources / pmfrthrd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-25  |  10.3 KB  |  342 lines

  1. /*--------------------------------------------------
  2.    PMFRTHRD.C -- FRACTINT for PM
  3.  
  4.           Background Processing Control Module
  5.           (typically  called a Thread)
  6.  
  7.    03/17/91      Code by Donald P. Egen
  8.  
  9.    This module's main function (PMfrThread) is the
  10.    main function for the background thread.
  11.    It initializes and waits until posted to do
  12.    something by the main (user/PM interface) thread.
  13.    Part of this initialization is to let each possible
  14.    called driver initialize, if necessary.
  15.    One "something" to do is to shut down.
  16.    Other "somethings" are long-running processes,
  17.    such as the actual calculation of the Fractal
  18.    Engine, and printing, saving, and loading.
  19.  
  20.    This background control used to be part of
  21.    MANDCALC.  It was split off to be able to
  22.    add in print, save, and load actions.
  23.    (And who knows what else eventually).
  24.  
  25.    Subroutines needed for PM interface by all
  26.    (or at least some) background thread actions
  27.    are also in this module.
  28.  
  29.    This is architected as a single thread that can
  30.    do one of multiple actions.  This is OK for now
  31.    since you don't want to Print while still Calculating,
  32.    or whatever.  The actions are mutually exclusive
  33.    and not viable running concurrently.
  34.  ---------------------------------------------------*/
  35.  
  36. #define INCL_WIN
  37. #define INCL_GPI
  38. #define INCL_DOS
  39. #include <os2.h>
  40. #include <process.h>
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <setjmp.h>
  44. #include <float.h>
  45. #include <malloc.h>
  46. #include <smplhelp.h>
  47.  
  48. #include "pmfract.h"
  49. #include "fractint.h"
  50. #include "fractype.h"
  51.  
  52. HAB    habThread;
  53.  
  54. VOID FAR PMfrThread (VOID)
  55.      {
  56.      int sub_rc;
  57.  
  58.      habThread = WinInitialize(0);
  59.  
  60.      WinGetLastError(habThread);
  61.  
  62.    /* get the memory DC */
  63.    cp.hdcMemory = DevOpenDC (habThread, OD_MEMORY, "*", 0L, NULL, NULL) ;
  64.    /* this says that we don't have a PS yet; not one to destroy */
  65.    cp.hpsMemory = (HPS) NULL;
  66.  
  67.      /* let each sub-driver have a crack at it now */
  68.      PrintDriverInit();
  69.      CalcDriverInit();
  70.  
  71.      /* Initialization here is done.
  72.         Post main thread that we are going to work
  73.      */
  74.  
  75.      WinPostMsg(cp.hwnd, WM_THRD_POST,
  76.                 MPFROM2SHORT(SUB_INIT_DONE, 0),
  77.                 MPFROMP(NULL) );
  78.  
  79.      for (;;)
  80.           {  /* wait for something to do */
  81.           DosSemWait (&cp.ulSemTrigger, SEM_INDEFINITE_WAIT) ;
  82.  
  83.           /* take an early exit for Shutdown */
  84.           if (cp.sSubAction == SUB_ACT_TERM)
  85.              break;
  86.  
  87.           /* posted out of wait.  do something */
  88.  
  89.           switch(cp.sSubAction)
  90.                 {
  91.                 case SUB_ACT_CALC:
  92.                      sub_rc = CalcDriver();
  93.                      break;
  94.                 case SUB_ACT_PRINT:
  95.                      sub_rc = PrintDriver();
  96.                      break;
  97.                 case SUB_ACT_SAVE:
  98.                      sub_rc = SaveDriver();
  99.                      break;
  100.                 case SUB_ACT_LOAD:
  101.                      sub_rc = LoadDriver();
  102.                      break;
  103.                 default:
  104.                      sub_rc = 0x9999;   /* let the main task figure it out */
  105.                      break;
  106.                 }
  107.  
  108.           /* test here for shutdown also */
  109.           if (cp.sSubAction == SUB_ACT_TERM)
  110.               break;
  111.  
  112.           /* not shutdown. */
  113.           /* indicate ready for the next cycle */
  114.           DosSemSet (&cp.ulSemTrigger) ;
  115.           WinPostMsg (cp.hwnd, WM_THRD_POST, MPFROM2SHORT(sub_rc, 0) ,
  116.                          MPFROMP(NULL) ) ;
  117.           }
  118.  
  119.       /* shutdown has been triggered.
  120.          release resources obtained by us.
  121.  
  122.          NOTE: Serialize using DosEnterCritSec so that
  123.          the main thread is dormant until we get everything
  124.          cleaned up and go away.  The main thread will be
  125.          re-dispatched following our final DosExit.
  126.       */
  127.  
  128.       DosEnterCritSec();
  129.  
  130.       if (cp.hpsMemory != (HPS) 0)
  131.          {  /* protection from a failed WM_CREATE or IDM_GO */
  132.          GpiSetBitmap(cp.hpsMemory, (HBITMAP) NULL);
  133.          GpiDestroyPS(cp.hpsMemory);
  134.          GpiDeleteBitmap (cp.hbmMemory);
  135.          }
  136.       cp.hpsMemory = (HPS) 0;
  137.  
  138.       if ( cp.pixels != NULL)
  139.          hfree(cp.pixels);
  140.       cp.pixels = NULL;
  141.  
  142.       if (cp.hdcMemory != (HDC) 0)
  143.          DevCloseDC (cp.hdcMemory);
  144.       cp.hdcMemory = (HDC) 0;
  145.  
  146.       /* say good-bye to PM */
  147.       WinTerminate(habThread);
  148.  
  149.       /* flag we done */
  150.       DosSemClear ((HSEM) &cp.ulSemSubEnded);
  151.       /* and go away */
  152.       DosExit(EXIT_THREAD, 0);
  153.  
  154.       }
  155.  
  156. /*
  157.  *   Get or Resize the memory bitmap, memory presentation space,
  158.  *   and the pixel array.
  159.  *
  160.  *   return FALSE on OK
  161.  *   return TRUE on ERROR.
  162.  *    This allows
  163.  *        if (GetMemoryBitmap(...) )
  164.  *              { error.... }
  165.  */
  166.  
  167. BOOL GetMemoryBitmap (HAB hab)
  168.      {
  169.      SIZEL sizl;
  170.      BITMAPINFOHEADER bmp, bmpQQ;
  171.      RECTL rcl;
  172.      LONG   alBmpFormats[12];
  173.      LONG errorcode;
  174.      int  i, j;
  175.      LONG pm_bytes, li;
  176.      unsigned char _huge *phc;
  177.  
  178.      /* serialize destroy/create */
  179.      DosSemRequest((HSEM) &cp.ulSemMemPS, SEM_INDEFINITE_WAIT);
  180.  
  181.      /* set the sizl and rcl values */
  182.      sizl.cx = (LONG) cp.cx;
  183.      sizl.cy = (LONG) cp.cy;
  184.      rcl.xLeft = 0;
  185.      rcl.yBottom = 0;
  186.      rcl.xRight = cp.cx;
  187.      rcl.yTop = cp.cy;
  188.  
  189.      /* start by assuming 256-color */
  190.      cp.pm_xdots = ((ULONG) cp.cx + 3) & 0xFFFFFFFC;
  191.      cp.pixelshift_per_byte = 0;
  192.      cp.pixels_per_byte   = 1;
  193.      cp.pixels_per_bytem1 = 0;
  194.      cp.cPlanes = 1;
  195.      cp.cBitCount = 8;
  196.      cp.sCurrentPalette = IDD_PAL_VGA256;
  197.      cp.pbmiMemory = &bmiColorTableVGA256;
  198.  
  199.      if (cp.colors == 16) { /* Wrong guess... */
  200.         cp.cPlanes = 1;
  201.         cp.cBitCount = 4;
  202.         cp.pixelshift_per_byte = 1;
  203.         cp.pm_xdots = (((ULONG) cp.cx + 7) & 0xfffffff8);
  204.         cp.pixels_per_byte = 2;
  205.         cp.pixels_per_bytem1 = 1;
  206.         cp.pm_andmask[0] = 0xf0;
  207.         cp.pm_notmask[0] = 0x0f;
  208.         cp.pm_bitshift[0] = 4;
  209.         cp.pm_andmask[1] = 0x0f;
  210.         cp.pm_notmask[1] = 0xf0;
  211.         cp.pm_bitshift[1] = 0;
  212.         cp.sCurrentPalette = IDD_PAL_VGA16;
  213.         cp.pbmiMemory = &bmiColorTableVGA16;
  214.         }
  215.  
  216.      if (cp.colors == 2) { /* ... or again ... */
  217.         cp.cPlanes = 1;
  218.         cp.cBitCount = 1;
  219.         cp.pixelshift_per_byte = 3;
  220.         cp.pm_xdots = (((ULONG) cp.cx+31) & 0xffffffe0);
  221.         cp.pixels_per_byte = 8;
  222.         cp.pixels_per_bytem1 = 7;
  223.         cp.pm_andmask[0] = 0x80;
  224.         cp.pm_notmask[0] = 0x7f;
  225.         cp.pm_bitshift[0] = 7;
  226.         for (i = 1; i < 8; i++) {
  227.             cp.pm_andmask[i] = cp.pm_andmask[i-1] >> 1;
  228.             cp.pm_notmask[i] = (cp.pm_notmask[i-1] >> 1) + 0x80;
  229.             cp.pm_bitshift[i] = cp.pm_bitshift[i-1] - 1;
  230.             }
  231.         cp.sCurrentPalette = IDD_PAL_BW;
  232.         cp.pbmiMemory = &bmiColorTableBW;
  233.         }
  234.  
  235.      cp.pm_xbytes = cp.pm_xdots >> cp.pixelshift_per_byte;
  236.      pm_bytes =  (LONG) cp.pm_xbytes * (LONG) cp.cy;
  237.  
  238.      errorcode = WinGetLastError(hab);
  239.  
  240.      /* destroy the old memory bitmap and ps if there is one */
  241.      if ( cp.hpsMemory != (HPS) NULL)
  242.         {
  243.         GpiSetBitmap(cp.hpsMemory, (HBITMAP) NULL);
  244.         GpiDestroyPS(cp.hpsMemory);
  245.         GpiDeleteBitmap (cp.hbmMemory);
  246.         }
  247.      if ( cp.pixels != NULL)
  248.         hfree(cp.pixels);
  249.  
  250.      /* now get the new presentation space, etc. */
  251.      cp.hpsMemory = GpiCreatePS (hab, cp.hdcMemory, &sizl,
  252.                     PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
  253.  
  254.      if (cp.hpsMemory == (HPS) 0)
  255.         return TRUE;
  256.  
  257.      /* and create the new bitmap */
  258.      GpiQueryDeviceBitmapFormats (cp.hpsMemory, 12L, alBmpFormats) ;
  259.      bmp.cbFix   = sizeof bmp;
  260.      bmp.cx      = cp.cx;
  261.      bmp.cy      = cp.cy;
  262.      bmp.cPlanes = cp.cPlanes;
  263.      bmp.cBitCount = cp.cBitCount;
  264.      cp.hbmMemory = GpiCreateBitmap (cp.hpsMemory, &bmp, 0L, NULL, NULL);
  265.      errorcode = WinGetLastError(hab);
  266.  
  267.      if (cp.hbmMemory == (HBITMAP) 0)
  268.            return TRUE;
  269.  
  270.      GpiSetBitmap (cp.hpsMemory, cp.hbmMemory);
  271.      errorcode = WinGetLastError(hab);
  272.      GpiQueryBitmapParameters(cp.hbmMemory, &bmpQQ);
  273.      errorcode = WinGetLastError(hab);
  274.  
  275.      /* initialize and black out the bitmap */
  276.      GpiSetMix ( cp.hpsMemory, FM_OVERPAINT) ;
  277.      GpiSetBackMix (cp.hpsMemory, BM_LEAVEALONE) ;
  278.      GpiCreateLogColorTable(cp.hpsMemory, LCOL_RESET | LCOL_REALIZABLE,
  279.               LCOLF_CONSECRGB, 0L, lScreenColors, alPhysicalColors);
  280.  
  281.      WinFillRect (cp.hpsMemory, &rcl, CLR_BLACK);
  282.  
  283.      /* ** KLUDGE ** */
  284.      /* unfortunately, if size sent to halloc is > 128K,
  285.         then the size of each element must be a multiple of 2.
  286.         halloc doesn't treat 1 as a multiple of 2 (although it is 2 ** 0)
  287.      */
  288.      pm_bytes = ( (pm_bytes + 7) & 0xfffffff8) >> 3;
  289.      cp.pixels = (unsigned char _huge *) halloc(pm_bytes, 8);
  290.      if (cp.pixels == NULL)
  291.           return TRUE;
  292.  
  293.      /* the book says he clears the memory for us */
  294.      /* for (phc = cp.pixels, li = 0; li <= pm_bytes; li++)  *phc++ = '\0'; */
  295.  
  296.      /* deserialize destroy/create */
  297.      DosSemClear ( (HSEM) &cp.ulSemMemPS ) ;
  298.  
  299.      return FALSE;
  300.      }
  301.  
  302.  /*
  303.   *  Synchronous Message Processing
  304.   *
  305.   *  The Fractint Fractal Calculation Engine needs to issue a message
  306.   *  and get a OK/CANCEL type response from time to time.
  307.   *  This is difficult given that it is a queueless subthread.
  308.   *  This function provides a synchronous interface to the main
  309.   *  user interface thread to present a message box and post
  310.   *  back the subthread with the user's response.
  311.   *
  312.   */
  313.  
  314. int FAR PMfrSyncMsg(int flags, PSZ msg)
  315.   {
  316.  
  317.   int result;
  318.  
  319.   /* ENQ on the first semaphore to ensure that only
  320.      one thread at a time is using this function */
  321.   DosSemRequest( (HSEM) &cp.ulSemSyncMsg, SEM_INDEFINITE_WAIT);
  322.  
  323.   /* initialize the return semaphore to wait for a response */
  324.   DosSemSet( (HSEM) &cp.ulSemSyncMsgDone);
  325.  
  326.   /* tell the main thread to ask the question */
  327.   WinPostMsg(cp.hwnd, WM_SYNC_MSG, MPFROMP(msg), MPFROM2SHORT(flags, 0) );
  328.  
  329.   /* now wait for the response */
  330.   DosSemWait( (HSEM) &cp.ulSemSyncMsgDone, SEM_INDEFINITE_WAIT);
  331.  
  332.   /* retrieve the response */
  333.   result = cp.SyncMsgAnswer;
  334.  
  335.   /* DEQ on this resource */
  336.   DosSemClear( (HSEM) &cp.ulSemSyncMsg);
  337.  
  338.   /* and go back */
  339.   return result;
  340.  
  341.   }
  342.