Example #1
0
static HRESULT WINAPI ddrawex_surface4_Blt(IDirectDrawSurface4 *iface, RECT *dst_rect,
        IDirectDrawSurface4 *src_surface, RECT *src_rect, DWORD flags, DDBLTFX *fx)
{
    struct ddrawex_surface *dst = impl_from_IDirectDrawSurface4(iface);
    struct ddrawex_surface *src = unsafe_impl_from_IDirectDrawSurface4(src_surface);

    TRACE("iface %p, dst_rect %s, src_surface %p, src_rect %s, flags %#x, fx %p.\n",
            iface, wine_dbgstr_rect(dst_rect), src_surface, wine_dbgstr_rect(src_rect), flags, fx);

    return IDirectDrawSurface4_Blt(dst->parent, dst_rect, src ? src->parent : NULL, src_rect, flags, fx);
}
static Bool
winRedrawScreenShadowDDNL (ScreenPtr pScreen)
{
  winScreenPriv(pScreen);
  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
  HRESULT		ddrval = DD_OK;
  RECT			rcSrc, rcDest;
  POINT			ptOrigin;

  /* Get the origin of the window in the screen coords */
  ptOrigin.x = pScreenInfo->dwXOffset;
  ptOrigin.y = pScreenInfo->dwYOffset;
  MapWindowPoints (pScreenPriv->hwndScreen,
		   HWND_DESKTOP,
		   (LPPOINT)&ptOrigin, 1);
  rcDest.left = ptOrigin.x;
  rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
  rcDest.top = ptOrigin.y;
  rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;

  /* Source can be entire shadow surface, as Blt should clip for us */
  rcSrc.left = 0;
  rcSrc.top = 0;
  rcSrc.right = pScreenInfo->dwWidth;
  rcSrc.bottom = pScreenInfo->dwHeight;

  /* Redraw the whole window, to take account for the new colors */
  ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
				    &rcDest,
				    pScreenPriv->pddsShadow4,
				    &rcSrc,
				    DDBLT_WAIT,
				    NULL);
  if (FAILED (ddrval))
    {
      ErrorF ("winRedrawScreenShadowDDNL - IDirectDrawSurface4_Blt () "
	      "failed: %08x\n",
	      (unsigned int) ddrval);
    }

  return TRUE;
}
static Bool
winBltExposedRegionsShadowDDNL (ScreenPtr pScreen)
{
  winScreenPriv(pScreen);
  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
  RECT			rcSrc, rcDest;
  POINT			ptOrigin;
  HDC			hdcUpdate;
  PAINTSTRUCT		ps;
  HRESULT		ddrval = DD_OK;
  Bool			fReturn = TRUE;
  int			i;

  /* Quite common case. The primary surface was lost (maybe because of depth
   * change). Try to create a new primary surface. Bail out if this fails */
  if (pScreenPriv->pddsPrimary4 == NULL && pScreenPriv->fRetryCreateSurface &&
      !winCreatePrimarySurfaceShadowDDNL(pScreen))
    {
      Sleep(100);
      return FALSE;
    }
  if (pScreenPriv->pddsPrimary4 == NULL)
    return FALSE;  
  
  /* BeginPaint gives us an hdc that clips to the invalidated region */
  hdcUpdate = BeginPaint (pScreenPriv->hwndScreen, &ps);
  if (hdcUpdate == NULL)
    {
      fReturn = FALSE;
      ErrorF ("winBltExposedRegionsShadowDDNL - BeginPaint () returned "
	      "a NULL device context handle.  Aborting blit attempt.\n");
      goto winBltExposedRegionsShadowDDNL_Exit;
    }

  /* Get the origin of the window in the screen coords */
  ptOrigin.x = pScreenInfo->dwXOffset;
  ptOrigin.y = pScreenInfo->dwYOffset;

  MapWindowPoints (pScreenPriv->hwndScreen,
		   HWND_DESKTOP,
		   (LPPOINT)&ptOrigin, 1);
  rcDest.left = ptOrigin.x;
  rcDest.right = ptOrigin.x + pScreenInfo->dwWidth;
  rcDest.top = ptOrigin.y;
  rcDest.bottom = ptOrigin.y + pScreenInfo->dwHeight;

  /* Source can be entire shadow surface, as Blt should clip for us */
  rcSrc.left = 0;
  rcSrc.top = 0;
  rcSrc.right = pScreenInfo->dwWidth;
  rcSrc.bottom = pScreenInfo->dwHeight;

  /* Try to regain the primary surface and blit again if we've lost it */
  for (i = 0; i <= WIN_REGAIN_SURFACE_RETRIES; ++i)
    {
      /* Our Blt should be clipped to the invalidated region */
      ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
					&rcDest,
					pScreenPriv->pddsShadow4,
					&rcSrc,
					DDBLT_WAIT,
					NULL);
      if (ddrval == DDERR_SURFACELOST)
	{
	  /* Surface was lost */
	  winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
          "IDirectDrawSurface4_Blt reported that the primary "
          "surface was lost, trying to restore, retry: %d\n", i + 1);

	  /* Try to restore the surface, once */
	  
	  ddrval = IDirectDrawSurface4_Restore (pScreenPriv->pddsPrimary4);
	  winDebug ("winBltExposedRegionsShadowDDNL - "
		  "IDirectDrawSurface4_Restore returned: ");
	  if (ddrval == DD_OK)
	    winDebug ("DD_OK\n");
	  else if (ddrval == DDERR_WRONGMODE)
	    winDebug ("DDERR_WRONGMODE\n");
	  else if (ddrval == DDERR_INCOMPATIBLEPRIMARY)
	    winDebug ("DDERR_INCOMPATIBLEPRIMARY\n");
	  else if (ddrval == DDERR_UNSUPPORTED)
	    winDebug ("DDERR_UNSUPPORTED\n");
	  else if (ddrval == DDERR_INVALIDPARAMS)
	    winDebug ("DDERR_INVALIDPARAMS\n");
	  else if (ddrval == DDERR_INVALIDOBJECT)
	    winDebug ("DDERR_INVALIDOBJECT\n");
	  else
	    winDebug ("unknown error: %08x\n", (unsigned int) ddrval);
	  
	  /* Loop around to try the blit one more time */
	  continue;
	}  
      else if (FAILED (ddrval))
	{
	  fReturn = FALSE;
	  winErrorFVerb (1, "winBltExposedRegionsShadowDDNL - "
		  "IDirectDrawSurface4_Blt failed, but surface not "
		  "lost: %08x %d\n",
		  (unsigned int) ddrval, (int) ddrval);
	  goto winBltExposedRegionsShadowDDNL_Exit;
	}
      else
	{
	  /* Success, stop looping */
	  break;
	}
    }

 winBltExposedRegionsShadowDDNL_Exit:
  /* EndPaint frees the DC */
  if (hdcUpdate != NULL)
    EndPaint (pScreenPriv->hwndScreen, &ps);
  return fReturn;
}
static void
winShadowUpdateDDNL (ScreenPtr pScreen, 
		     shadowBufPtr pBuf)
{
  winScreenPriv(pScreen);
  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
  RegionPtr		damage = shadowDamage(pBuf);
  HRESULT		ddrval = DD_OK;
  RECT			rcDest, rcSrc;
  POINT			ptOrigin;
  DWORD			dwBox = RegionNumRects (damage);
  BoxPtr		pBox = RegionRects (damage);
  HRGN			hrgnTemp = NULL, hrgnCombined = NULL;

  /*
   * Return immediately if the app is not active
   * and we are fullscreen, or if we have a bad display depth
   */
  if ((!pScreenPriv->fActive && pScreenInfo->fFullScreen)
      || pScreenPriv->fBadDepth) return;

  /* Return immediately if we didn't get needed surfaces */
  if (!pScreenPriv->pddsPrimary4 || !pScreenPriv->pddsShadow4)
    return;

  /* Get the origin of the window in the screen coords */
  ptOrigin.x = pScreenInfo->dwXOffset;
  ptOrigin.y = pScreenInfo->dwYOffset;
  MapWindowPoints (pScreenPriv->hwndScreen,
		   HWND_DESKTOP,
		   (LPPOINT)&ptOrigin, 1);

  /*
   * Handle small regions with multiple blits,
   * handle large regions by creating a clipping region and 
   * doing a single blit constrained to that clipping region.
   */
  if (pScreenInfo->dwClipUpdatesNBoxes == 0
      || dwBox < pScreenInfo->dwClipUpdatesNBoxes)
    {
      /* Loop through all boxes in the damaged region */
      while (dwBox--)
	{
	  /* Assign damage box to source rectangle */
	  rcSrc.left = pBox->x1;
	  rcSrc.top = pBox->y1;
	  rcSrc.right = pBox->x2;
	  rcSrc.bottom = pBox->y2;
	  
	  /* Calculate destination rectangle */
	  rcDest.left = ptOrigin.x + rcSrc.left;
	  rcDest.top = ptOrigin.y + rcSrc.top;
	  rcDest.right = ptOrigin.x + rcSrc.right;
	  rcDest.bottom = ptOrigin.y + rcSrc.bottom;
	  
	  /* Blit the damaged areas */
	  ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
					    &rcDest,
					    pScreenPriv->pddsShadow4,
					    &rcSrc,
					    DDBLT_WAIT,
					    NULL);
	  if (FAILED (ddrval))
	    {
	      static int	s_iFailCount = 0;
	      
	      if (s_iFailCount < FAIL_MSG_MAX_BLT)
		{
		  ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt () "
			  "failed: %08x\n",
			  (unsigned int) ddrval);
		  
		  ++s_iFailCount;

		  if (s_iFailCount == FAIL_MSG_MAX_BLT)
		    {
		      ErrorF ("winShadowUpdateDDNL - IDirectDrawSurface4_Blt "
			      "failure message maximum (%d) reached.  No "
			      "more failure messages will be printed.\n",
			      FAIL_MSG_MAX_BLT);
		    }
		}
	    }
	  
	  /* Get a pointer to the next box */
	  ++pBox;
	}
    }
  else
    {
      BoxPtr		pBoxExtents = RegionExtents(damage);

      /* Compute a GDI region from the damaged region */
      hrgnCombined = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
      dwBox--;
      pBox++;
      while (dwBox--)
	{
	  hrgnTemp = CreateRectRgn (pBox->x1, pBox->y1, pBox->x2, pBox->y2);
	  CombineRgn (hrgnCombined, hrgnCombined, hrgnTemp, RGN_OR);
	  DeleteObject (hrgnTemp);
	  pBox++;
	}

      /* Install the GDI region as a clipping region */
      SelectClipRgn (pScreenPriv->hdcScreen, hrgnCombined);
      DeleteObject (hrgnCombined);
      hrgnCombined = NULL;

#if CYGDEBUG
      winDebug ("winShadowUpdateDDNL - be x1 %d y1 %d x2 %d y2 %d\n",
	      pBoxExtents->x1, pBoxExtents->y1,
	      pBoxExtents->x2, pBoxExtents->y2);
#endif

      /* Calculating a bounding box for the source is easy */
      rcSrc.left = pBoxExtents->x1;
      rcSrc.top = pBoxExtents->y1;
      rcSrc.right = pBoxExtents->x2;
      rcSrc.bottom = pBoxExtents->y2;

      /* Calculating a bounding box for the destination is trickier */
      rcDest.left = ptOrigin.x + rcSrc.left;
      rcDest.top = ptOrigin.y + rcSrc.top;
      rcDest.right = ptOrigin.x + rcSrc.right;
      rcDest.bottom = ptOrigin.y + rcSrc.bottom;

      /* Our Blt should be clipped to the invalidated region */
      ddrval = IDirectDrawSurface4_Blt (pScreenPriv->pddsPrimary4,
					&rcDest,
					pScreenPriv->pddsShadow4,
					&rcSrc,
					DDBLT_WAIT,
					NULL);

      /* Reset the clip region */
      SelectClipRgn (pScreenPriv->hdcScreen, NULL);
    }
}