예제 #1
0
/**
 * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
 * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
 */
LRESULT CALLBACK
stw_call_window_proc(int nCode, WPARAM wParam, LPARAM lParam)
{
   struct stw_tls_data *tls_data;
   PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
   struct stw_framebuffer *fb;

   tls_data = stw_tls_get_data();
   if (!tls_data)
      return 0;

   if (nCode < 0 || !stw_dev)
       return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);

   /* We check that the stw_dev object is initialized before we try to do
    * anything with it.  Otherwise, in multi-threaded programs there's a
    * chance of executing this code before the stw_dev object is fully
    * initialized.
    */
   if (stw_dev && stw_dev->initialized) {
      if (pParams->message == WM_WINDOWPOSCHANGED) {
         /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according
          * to http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx
          * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it
          * can be masked out by the application.
          */
         LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
         if ((lpWindowPos->flags & SWP_SHOWWINDOW) ||
             !(lpWindowPos->flags & SWP_NOMOVE) ||
             !(lpWindowPos->flags & SWP_NOSIZE)) {
            fb = stw_framebuffer_from_hwnd( pParams->hwnd );
            if (fb) {
               /* Size in WINDOWPOS includes the window frame, so get the size
                * of the client area via GetClientRect.
                */
               stw_framebuffer_get_size(fb);
               stw_framebuffer_unlock(fb);
            }
         }
      }
      else if (pParams->message == WM_DESTROY) {
         stw_lock_framebuffers(stw_dev);
         fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
         if (fb)
            stw_framebuffer_release_locked(fb);
         stw_unlock_framebuffers(stw_dev);
      }
   }

   return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
}
예제 #2
0
/**
 * Update the framebuffer's size if necessary.
 */
void
stw_framebuffer_update(struct stw_framebuffer *fb)
{
   assert(fb->stfb);
   assert(fb->height);
   assert(fb->width);

   /* XXX: It would be nice to avoid checking the size again -- in theory
    * stw_call_window_proc would have cought the resize and stored the right
    * size already, but unfortunately threads created before the DllMain is
    * called don't get a DLL_THREAD_ATTACH notification, and there is no way
    * to know of their existing without using the not very portable PSAPI.
    */
   stw_framebuffer_get_size(fb);
}
예제 #3
0
/**
 * @sa http://msdn.microsoft.com/en-us/library/ms644975(VS.85).aspx
 * @sa http://msdn.microsoft.com/en-us/library/ms644960(VS.85).aspx
 */
LRESULT CALLBACK
stw_call_window_proc(
   int nCode,
   WPARAM wParam,
   LPARAM lParam )
{
   struct stw_tls_data *tls_data;
   PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
   struct stw_framebuffer *fb;
   
   tls_data = stw_tls_get_data();
   if(!tls_data)
      return 0;
   
   if (nCode < 0 || !stw_dev)
       return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);

   if (pParams->message == WM_WINDOWPOSCHANGED)
   {
      /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according to
       * http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx 
       * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it 
       * can be masked out by the application. */
      LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
      if((lpWindowPos->flags & SWP_SHOWWINDOW) || 
         !(lpWindowPos->flags & SWP_NOMOVE) ||
         !(lpWindowPos->flags & SWP_NOSIZE)) {
         fb = stw_framebuffer_from_hwnd( pParams->hwnd );
         if(fb) {
            /* Size in WINDOWPOS includes the window frame, so get the size 
             * of the client area via GetClientRect.  */
            stw_framebuffer_get_size(fb);
            stw_framebuffer_release(fb);
         }
      }
   }
   else if (pParams->message == WM_DESTROY) {
      pipe_mutex_lock( stw_dev->fb_mutex );
      fb = stw_framebuffer_from_hwnd_locked( pParams->hwnd );
      if(fb)
         stw_framebuffer_destroy_locked(fb);
      pipe_mutex_unlock( stw_dev->fb_mutex );
   }

   return CallNextHookEx(tls_data->hCallWndProcHook, nCode, wParam, lParam);
}
예제 #4
0
/**
 * Create a new stw_framebuffer object which corresponds to the given
 * HDC/window.  If successful, we return the new stw_framebuffer object
 * with its mutex locked.
 */
struct stw_framebuffer *
stw_framebuffer_create(HDC hdc, int iPixelFormat)
{
   HWND hWnd;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;

   /* We only support drawing to a window. */
   hWnd = WindowFromDC( hdc );
   if (!hWnd)
      return NULL;

   fb = CALLOC_STRUCT( stw_framebuffer );
   if (fb == NULL)
      return NULL;

   fb->hWnd = hWnd;
   fb->iPixelFormat = iPixelFormat;

   /*
    * We often need a displayable pixel format to make GDI happy. Set it
    * here (always 1, i.e., out first pixel format) where appropriate.
    */
   fb->iDisplayablePixelFormat = iPixelFormat <= stw_dev->pixelformat_count
      ? iPixelFormat : 1;

   fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat );
   fb->stfb = stw_st_create_framebuffer( fb );
   if (!fb->stfb) {
      FREE( fb );
      return NULL;
   }

   fb->refcnt = 1;

   /*
    * Windows can be sometimes have zero width and or height, but we ensure
    * a non-zero framebuffer size at all times.
    */

   fb->must_resize = TRUE;
   fb->width  = 1;
   fb->height = 1;
   fb->client_rect.left   = 0;
   fb->client_rect.top    = 0;
   fb->client_rect.right  = fb->client_rect.left + fb->width;
   fb->client_rect.bottom = fb->client_rect.top  + fb->height;

   stw_framebuffer_get_size(fb);

   InitializeCriticalSection(&fb->mutex);

   /* This is the only case where we lock the stw_framebuffer::mutex before
    * stw_dev::fb_mutex, since no other thread can know about this framebuffer
    * and we must prevent any other thread from destroying it before we return.
    */
   stw_framebuffer_lock(fb);

   stw_lock_framebuffers(stw_dev);
   fb->next = stw_dev->fb_head;
   stw_dev->fb_head = fb;
   stw_unlock_framebuffers(stw_dev);

   return fb;
}
예제 #5
0
struct stw_framebuffer *
stw_framebuffer_create(
   HDC hdc,
   int iPixelFormat )
{
   HWND hWnd;
   struct stw_framebuffer *fb;
   const struct stw_pixelformat_info *pfi;

   /* We only support drawing to a window. */
   hWnd = WindowFromDC( hdc );
   if(!hWnd)
      return NULL;
   
   fb = CALLOC_STRUCT( stw_framebuffer );
   if (fb == NULL)
      return NULL;

   /* Applications use, create, destroy device contexts, so the hdc passed is.  We create our own DC
    * because we need one for single buffered visuals.
    */
   fb->hDC = GetDC(hWnd);

   fb->hWnd = hWnd;
   fb->iPixelFormat = iPixelFormat;

   fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat - 1 );
   fb->stfb = stw_st_create_framebuffer( fb );
   if (!fb->stfb) {
      FREE( fb );
      return NULL;
   }

   fb->refcnt = 1;

   /*
    * Windows can be sometimes have zero width and or height, but we ensure
    * a non-zero framebuffer size at all times.
    */

   fb->must_resize = TRUE;
   fb->width  = 1;
   fb->height = 1;
   fb->client_rect.left   = 0;
   fb->client_rect.top    = 0;
   fb->client_rect.right  = fb->client_rect.left + fb->width;
   fb->client_rect.bottom = fb->client_rect.top  + fb->height;

   stw_framebuffer_get_size(fb);

   pipe_mutex_init( fb->mutex );

   /* This is the only case where we lock the stw_framebuffer::mutex before
    * stw_dev::fb_mutex, since no other thread can know about this framebuffer
    * and we must prevent any other thread from destroying it before we return.
    */
   pipe_mutex_lock( fb->mutex );

   pipe_mutex_lock( stw_dev->fb_mutex );
   fb->next = stw_dev->fb_head;
   stw_dev->fb_head = fb;
   pipe_mutex_unlock( stw_dev->fb_mutex );

   return fb;
}