Exemple #1
0
void
miWindowExposures(WindowPtr pWin, RegionPtr prgn)
{
    RegionPtr exposures = prgn;

    if (prgn && !RegionNil(prgn)) {
        RegionRec expRec;
        int clientInterested =
            (pWin->eventMask | wOtherEventMasks(pWin)) & ExposureMask;
        if (clientInterested && (RegionNumRects(prgn) > RECTLIMIT)) {
            /*
             * If we have LOTS of rectangles, we decide to take the extents
             * and force an exposure on that.  This should require much less
             * work overall, on both client and server.  This is cheating, but
             * isn't prohibited by the protocol ("spontaneous combustion" :-).
             */
            BoxRec box = *RegionExtents(prgn);
            exposures = &expRec;
            RegionInit(exposures, &box, 1);
            RegionReset(prgn, &box);
            /* miPaintWindow doesn't clip, so we have to */
            RegionIntersect(prgn, prgn, &pWin->clipList);
        }
        pWin->drawable.pScreen->PaintWindow(pWin, prgn, PW_BACKGROUND);
        if (clientInterested)
            miSendExposures(pWin, exposures,
                            pWin->drawable.x, pWin->drawable.y);
        if (exposures == &expRec)
            RegionUninit(exposures);
        RegionEmpty(prgn);
    }
}
Exemple #2
0
int
ProcXFixesFetchRegion (ClientPtr client)
{
    RegionPtr		    pRegion;
    xXFixesFetchRegionReply *reply;
    xRectangle		    *pRect;
    BoxPtr		    pExtent;
    BoxPtr		    pBox;
    int			    i, nBox;
    REQUEST(xXFixesFetchRegionReq);

    REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
    VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);

    pExtent = RegionExtents(pRegion);
    pBox = RegionRects (pRegion);
    nBox = RegionNumRects (pRegion);
    
    reply = malloc(sizeof (xXFixesFetchRegionReply) +
		    nBox * sizeof (xRectangle));
    if (!reply)
	return BadAlloc;
    reply->type = X_Reply;
    reply->sequenceNumber = client->sequence;
    reply->length = nBox << 1;
    reply->x = pExtent->x1;
    reply->y = pExtent->y1;
    reply->width = pExtent->x2 - pExtent->x1;
    reply->height = pExtent->y2 - pExtent->y1;

    pRect = (xRectangle *) (reply + 1);
    for (i = 0; i < nBox; i++)
    {
	pRect[i].x = pBox[i].x1;
	pRect[i].y = pBox[i].y1;
	pRect[i].width = pBox[i].x2 - pBox[i].x1;
	pRect[i].height = pBox[i].y2 - pBox[i].y1;
    }
    if (client->swapped)
    {
	int n;
	swaps (&reply->sequenceNumber, n);
	swapl (&reply->length, n);
	swaps (&reply->x, n);
	swaps (&reply->y, n);
	swaps (&reply->width, n);
	swaps (&reply->height, n);
	SwapShorts ((INT16 *) pRect, nBox * 4);
    }
    (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) +
			 nBox * sizeof (xRectangle), (char *) reply);
    free(reply);
    return Success;
}
Exemple #3
0
static Bool
localResizeOffscreenLinear(FBLinearPtr resize, int length)
{
    FBManagerPtr offman;
    FBLinearLinkPtr pLink;
    ScreenPtr pScreen = resize->pScreen;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    pLink = offman->LinearAreas;
    if (!pLink)
        return FALSE;

    while (&(pLink->linear) != resize) {
        pLink = pLink->next;
        if (!pLink)
            return FALSE;
    }

    /* This could actually be alot smarter and try to move allocations
       from XY to linear when available.  For now if it was XY, we keep
       it XY */

    if (pLink->area) {          /* really an XY area */
        BoxPtr extents;
        int pitch, w, h;

        extents = RegionExtents(offman->InitialBoxes);
        pitch = extents->x2 - extents->x1;

        if (length < pitch) {   /* special case */
            w = length;
            h = 1;
        }
        else {
            w = pitch;
            h = (length + pitch - 1) / pitch;
        }

        if (localResizeOffscreenArea(pLink->area, w, h)) {
            resize->size = h * w;
            resize->offset =
                (pitch * pLink->area->box.y1) + pLink->area->box.x1;
            return TRUE;
        }
    }
    else {
        /* TODO!!!! resize the linear area */
    }

    return FALSE;
}
Exemple #4
0
RegionPtr
XFixesRegionCopy(RegionPtr pRegion)
{
    RegionPtr pNew = RegionCreate(RegionExtents(pRegion),
                                  RegionNumRects(pRegion));

    if (!pNew)
        return 0;
    if (!RegionCopy(pNew, pRegion)) {
        RegionDestroy(pNew);
        return 0;
    }
    return pNew;
}
Exemple #5
0
int
ProcXFixesRegionExtents (ClientPtr client)
{
    RegionPtr	pSource, pDestination;
    REQUEST(xXFixesRegionExtentsReq);

    REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
    VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
    VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);

    RegionReset(pDestination, RegionExtents(pSource));

    return Success;
}
Exemple #6
0
static int
ephyrPutVideo(KdScreenInfo * a_info,
              DrawablePtr a_drawable,
              short a_vid_x, short a_vid_y,
              short a_drw_x, short a_drw_y,
              short a_vid_w, short a_vid_h,
              short a_drw_w, short a_drw_h,
              RegionPtr a_clipping_region, pointer a_port_priv)
{
    EphyrPortPriv *port_priv = a_port_priv;
    BoxRec clipped_area, dst_box;
    int result = BadImplementation;
    int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0;

    EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, BadValue);
    EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);

    EPHYR_LOG("enter\n");

    dst_box.x1 = a_drw_x;
    dst_box.x2 = a_drw_x + a_drw_w;
    dst_box.y1 = a_drw_y;
    dst_box.y2 = a_drw_y + a_drw_h;

    if (!DoSimpleClip(&dst_box,
                      RegionExtents(a_clipping_region), &clipped_area)) {
        EPHYR_LOG_ERROR("failed to simple clip\n");
        goto out;
    }

    drw_x = clipped_area.x1;
    drw_y = clipped_area.y1;
    drw_w = clipped_area.x2 - clipped_area.x1;
    drw_h = clipped_area.y2 - clipped_area.y1;

    if (!ephyrHostXVPutVideo(a_info->pScreen->myNum,
                             port_priv->port_number,
                             a_vid_x, a_vid_y, a_vid_w, a_vid_h,
                             a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
        EPHYR_LOG_ERROR("ephyrHostXVPutVideo() failed\n");
        goto out;
    }
    result = Success;

 out:
    EPHYR_LOG("leave\n");
    return result;
}
Exemple #7
0
static Bool
localQueryLargestOffscreenLinear(ScreenPtr pScreen,
                                 int *size, int gran, int priority)
{
    FBManagerPtr offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                                          xf86FBScreenKey);
    FBLinearLinkPtr pLink;
    FBLinearLinkPtr pLinkRet;

    *size = 0;

    pLink = offman->LinearAreas;

    if (pLink && !pLink->area) {
        pLinkRet = pLink;
        while (pLink) {
            if (pLink->free) {
                if (pLink->linear.size > pLinkRet->linear.size)
                    pLinkRet = pLink;
            }
            pLink = pLink->next;
        }

        if (pLinkRet->free) {
            *size = pLinkRet->linear.size;
            return TRUE;
        }
    }
    else {
        int w, h;

        if (localQueryLargestOffscreenArea(pScreen, &w, &h, gran,
                                           FAVOR_WIDTH_THEN_AREA, priority)) {
            FBManagerPtr offman;
            BoxPtr extents;

            offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                                     xf86FBScreenKey);
            extents = RegionExtents(offman->InitialBoxes);
            if ((extents->x2 - extents->x1) == w)
                *size = w * h;
            return TRUE;
        }
    }

    return FALSE;
}
Exemple #8
0
FBAreaPtr
xf86AllocateLinearOffscreenArea(ScreenPtr pScreen,
                                int length,
                                int gran,
                                MoveAreaCallbackProcPtr moveCB,
                                RemoveAreaCallbackProcPtr removeCB,
                                void *privData)
{
    FBManagerFuncsPtr funcs;
    FBManagerPtr offman;
    BoxPtr extents;
    int w, h;

    if (xf86FBManagerKey == NULL)
        return NULL;
    if (!(funcs = (FBManagerFuncsPtr) dixLookupPrivate(&pScreen->devPrivates,
                                                       xf86FBManagerKey)))
        return NULL;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);
    extents = RegionExtents(offman->InitialBoxes);
    w = extents->x2 - extents->x1;

    if (gran > 1) {
        if (gran > w)
            return NULL;

        if (w % gran)
            length += gran - 1;
    }

    if (length <= w) {          /* special case */
        h = 1;
        w = length;
    }
    else {
        h = (length + w - 1) / w;
    }

    return (*funcs->AllocateOffscreenArea) (pScreen, w, h, gran, moveCB,
                                            removeCB, privData);
}
static void
DamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
    DamageExtPtr    pDamageExt = closure;

    switch (pDamageExt->level) {
    case DamageReportRawRegion:
    case DamageReportDeltaRegion:
	DamageExtNotify (pDamageExt, RegionRects(pRegion), RegionNumRects(pRegion));
	break;
    case DamageReportBoundingBox:
	DamageExtNotify (pDamageExt, RegionExtents(pRegion), 1);
	break;
    case DamageReportNonEmpty:
	DamageExtNotify (pDamageExt, NullBox, 0);
	break;
    case DamageReportNone:
	break;
    }
}
Exemple #10
0
static bool
fbGlyphIn(GCPtr gc, int x, int y, int width, int height)
{
	BoxRec box;
	BoxPtr extents = RegionExtents(gc->pCompositeClip);

	/*
	 * Check extents by hand to avoid 16 bit overflows
	 */
	if (x < (int) extents->x1 || (int) extents->x2 < x + width)
		return FALSE;
	if (y < (int) extents->y1 || (int) extents->y2 < y + height)
		return FALSE;

	box.x1 = x;
	box.x2 = x + width;
	box.y1 = y;
	box.y2 = y + height;
	return RegionContainsRect(gc->pCompositeClip, &box) == rgnIN;
}
Exemple #11
0
Bool
fbGlyphIn(RegionPtr pRegion, int x, int y, int width, int height)
{
    BoxRec box;
    BoxPtr pExtents = RegionExtents(pRegion);

    /*
     * Check extents by hand to avoid 16 bit overflows
     */
    if (x < (int) pExtents->x1)
        return FALSE;
    if ((int) pExtents->x2 < x + width)
        return FALSE;
    if (y < (int) pExtents->y1)
        return FALSE;
    if ((int) pExtents->y2 < y + height)
        return FALSE;
    box.x1 = x;
    box.x2 = x + width;
    box.y1 = y;
    box.y2 = y + height;
    return RegionContainsRect(pRegion, &box) == rgnIN;
}
Exemple #12
0
static void
winShadowUpdateGDI (ScreenPtr pScreen, 
		    shadowBufPtr pBuf)
{
  winScreenPriv(pScreen);
  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
  RegionPtr		damage = shadowDamage(pBuf);
  DWORD			dwBox = RegionNumRects (damage);
  BoxPtr		pBox = RegionRects (damage);
  int			x, y, w, h;
  HRGN			hrgnTemp = NULL, hrgnCombined = NULL;
#ifdef XWIN_UPDATESTATS
  static DWORD		s_dwNonUnitRegions = 0;
  static DWORD		s_dwTotalUpdates = 0;
  static DWORD		s_dwTotalBoxes = 0;
#endif
  BoxPtr		pBoxExtents = RegionExtents(damage);

  /*
   * 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;

#ifdef XWIN_UPDATESTATS
  ++s_dwTotalUpdates;
  s_dwTotalBoxes += dwBox;

  if (dwBox != 1)
    {
      ++s_dwNonUnitRegions;
      ErrorF ("winShadowUpdatGDI - dwBox: %d\n", dwBox);
    }
  
  if ((s_dwTotalUpdates % 100) == 0)
    ErrorF ("winShadowUpdateGDI - %d%% non-unity regions, avg boxes: %d "
	    "nu: %d tu: %d\n",
	    (s_dwNonUnitRegions * 100) / s_dwTotalUpdates,
	    s_dwTotalBoxes / s_dwTotalUpdates,
	    s_dwNonUnitRegions, s_dwTotalUpdates);
#endif /* XWIN_UPDATESTATS */

  /*
   * 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->fMultiWindow &&
      (pScreenInfo->dwClipUpdatesNBoxes == 0 ||
      dwBox < pScreenInfo->dwClipUpdatesNBoxes))
    {
      /* Loop through all boxes in the damaged region */
      while (dwBox--)
	{
	  /*
	   * Calculate x offset, y offset, width, and height for
	   * current damage box
	   */
	  x = pBox->x1;
	  y = pBox->y1;
	  w = pBox->x2 - pBox->x1;
	  h = pBox->y2 - pBox->y1;
	  
	  BitBlt (pScreenPriv->hdcScreen,
		  x, y,
		  w, h,
		  pScreenPriv->hdcShadow,
		  x, y,
		  SRCCOPY);
	  
	  /* Get a pointer to the next box */
	  ++pBox;
	}
    }
  else if (!pScreenInfo->fMultiWindow)
    {
      /* 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;
      
      /*
       * Blit the shadow buffer to the screen,
       * constrained to the clipping region.
       */
      BitBlt (pScreenPriv->hdcScreen,
	      pBoxExtents->x1, pBoxExtents->y1,
	      pBoxExtents->x2 - pBoxExtents->x1,
	      pBoxExtents->y2 - pBoxExtents->y1,
	      pScreenPriv->hdcShadow,
	      pBoxExtents->x1, pBoxExtents->y1,
	      SRCCOPY);

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

#ifdef XWIN_MULTIWINDOW
  /* Redraw all multiwindow windows */
  if (pScreenInfo->fMultiWindow)
    EnumThreadWindows (g_dwCurrentThreadID,
		       winRedrawDamagedWindowShadowGDI,
		       (LPARAM)pBoxExtents);
#endif
}
Exemple #13
0
static Bool
_glamor_copy_n_to_n(DrawablePtr src,
		    DrawablePtr dst,
		    GCPtr gc,
		    BoxPtr box,
		    int nbox,
		    int dx,
		    int dy,
		    Bool reverse,
		    Bool upsidedown, Pixel bitplane,
		    void *closure, Bool fallback)
{
	PixmapPtr dst_pixmap, src_pixmap;
	glamor_pixmap_private *dst_pixmap_priv, *src_pixmap_priv;
	glamor_screen_private *glamor_priv;
	glamor_gl_dispatch *dispatch;
	BoxPtr extent;
	RegionRec region;
	int src_x_off, src_y_off, dst_x_off, dst_y_off;
	Bool ok = FALSE;
	int force_clip = 0;

	if (nbox == 0)
		return TRUE;
	dst_pixmap = glamor_get_drawable_pixmap(dst);
	dst_pixmap_priv = glamor_get_pixmap_private(dst_pixmap);
	src_pixmap = glamor_get_drawable_pixmap(src);
	src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);

	glamor_priv = glamor_get_screen_private(dst->pScreen);

	DEBUGF("Copy %d %d %dx%d dx %d dy %d from %p to %p \n",
		box[0].x1, box[0].y1,
		box[0].x2 - box[0].x1, box[0].y2 - box[0].y1,
		dx, dy,
		src_pixmap, dst_pixmap);

	if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dst_pixmap_priv))
		goto fall_back;

	if (gc) {
		if (!glamor_set_planemask(dst_pixmap, gc->planemask))
			goto fall_back;
		dispatch = glamor_get_dispatch(glamor_priv);
		if (!glamor_set_alu(dispatch, gc->alu)) {
			glamor_put_dispatch(glamor_priv);
			goto fail_noregion;
		}
		glamor_put_dispatch(glamor_priv);
	}

	if (!src_pixmap_priv) {
		glamor_set_pixmap_type(src_pixmap, GLAMOR_MEMORY);
		src_pixmap_priv = glamor_get_pixmap_private(src_pixmap);
	}

	glamor_get_drawable_deltas(src, src_pixmap, &src_x_off,
				   &src_y_off);
	glamor_get_drawable_deltas(dst, dst_pixmap, &dst_x_off,
				   &dst_y_off);

	RegionInitBoxes(&region, box, nbox);
	extent = RegionExtents(&region);

	if (!glamor_check_fbo_size(glamor_priv,
		extent->x2 - extent->x1, extent->y2 - extent->y1)
	   && (src_pixmap_priv->type == GLAMOR_MEMORY
		|| (src_pixmap_priv == dst_pixmap_priv))) {
		force_clip = 1;
	}

	if (force_clip || dst_pixmap_priv->type == GLAMOR_TEXTURE_LARGE
	    || src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
			glamor_pixmap_clipped_regions *clipped_dst_regions;
			int n_dst_region, i, j;
			PixmapPtr temp_source_pixmap;
			glamor_pixmap_private *temp_source_priv = NULL;

			RegionTranslate(&region, dst_x_off, dst_y_off);
			if (!force_clip)
				clipped_dst_regions = glamor_compute_clipped_regions(dst_pixmap_priv,
										     &region, &n_dst_region, 0,
										     reverse, upsidedown);
			else
				clipped_dst_regions = glamor_compute_clipped_regions_ext(dst_pixmap_priv,
										         &region, &n_dst_region,
											 glamor_priv->max_fbo_size,
											 glamor_priv->max_fbo_size,
											 reverse, upsidedown);
			for(i = 0; i < n_dst_region; i++)
			{
				int n_src_region;
				glamor_pixmap_clipped_regions *clipped_src_regions;
				BoxPtr current_boxes;
				int n_current_boxes;

				SET_PIXMAP_FBO_CURRENT(dst_pixmap_priv, clipped_dst_regions[i].block_idx);

				temp_source_pixmap = NULL;
				if (src_pixmap_priv->type == GLAMOR_TEXTURE_LARGE) {
					RegionTranslate(clipped_dst_regions[i].region,
							-dst_x_off + src_x_off + dx, -dst_y_off + src_y_off + dy);
					clipped_src_regions = glamor_compute_clipped_regions(src_pixmap_priv,
											     clipped_dst_regions[i].region,
											     &n_src_region, 0,
											     reverse, upsidedown);
					DEBUGF("Source is large pixmap.\n");
					for (j = 0; j < n_src_region; j++)
					{
						if (src_pixmap_priv != dst_pixmap_priv)
							SET_PIXMAP_FBO_CURRENT(src_pixmap_priv, clipped_src_regions[j].block_idx);
						else if (src_pixmap_priv == dst_pixmap_priv &&
						    clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx) {
							/* source and the dest are the same, but need different block_idx.
							 * we create a empty pixmap and fill the required source fbo and box to
							 * it. It's a little hacky, but avoid extra copy. */
							temp_source_pixmap = glamor_create_pixmap(src->pScreen, 0, 0,
												  src->depth, 0);
							if (!temp_source_pixmap) {
								ok = FALSE;
								goto fail;
							}
							src->pScreen->ModifyPixmapHeader(temp_source_pixmap,
										      src_pixmap->drawable.width,
										      src_pixmap->drawable.height,
										      0, 0, src_pixmap->devKind, NULL);
							temp_source_priv = glamor_get_pixmap_private(temp_source_pixmap);
							*temp_source_priv = *src_pixmap_priv;
							temp_source_priv->large.box = src_pixmap_priv->large.box_array[clipped_src_regions[j].block_idx];
							temp_source_priv->base.fbo = src_pixmap_priv->large.fbo_array[clipped_src_regions[j].block_idx];
							temp_source_priv->base.pixmap = temp_source_pixmap;
						}
						assert(temp_source_pixmap || !(src_pixmap_priv == dst_pixmap_priv
							&& (clipped_src_regions[j].block_idx != clipped_dst_regions[i].block_idx)));

						RegionTranslate(clipped_src_regions[j].region,
								-src_x_off - dx,
								-src_y_off - dy);
						current_boxes = RegionRects(clipped_src_regions[j].region);
						n_current_boxes = RegionNumRects(clipped_src_regions[j].region);
						DEBUGF("dst pixmap fbo idx %d src pixmap fbo idx %d \n",
							clipped_dst_regions[i].block_idx,
							clipped_src_regions[j].block_idx);
						DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
							current_boxes[0].x1, current_boxes[0].y1,
							current_boxes[0].x2, current_boxes[0].y2,
							dx, dy, src_pixmap, dst_pixmap);
						if (!temp_source_pixmap)
							ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
										  n_current_boxes, dx, dy, reverse,
										  upsidedown, bitplane, closure);
						else {
							ok = __glamor_copy_n_to_n(&temp_source_pixmap->drawable,
										  dst, gc, current_boxes,
										  n_current_boxes, dx, dy, reverse,
										  upsidedown, bitplane, closure);
							temp_source_priv->type = GLAMOR_MEMORY;
							temp_source_priv->base.fbo = NULL;
							glamor_destroy_pixmap(temp_source_pixmap);
							temp_source_pixmap = NULL;
						}

						RegionDestroy(clipped_src_regions[j].region);
						if (!ok) {
							assert(0);
							goto fail;
						}
					}

					if (n_src_region == 0)
						ok = TRUE;
					free(clipped_src_regions);
				} else {
					RegionTranslate(clipped_dst_regions[i].region,
							- dst_x_off,
							- dst_y_off);
					current_boxes = RegionRects(clipped_dst_regions[i].region);
					n_current_boxes = RegionNumRects(clipped_dst_regions[i].region);

						DEBUGF("dest pixmap fbo idx %d \n",
							clipped_dst_regions[i].block_idx);
						DEBUGF("Copy %d %d %d %d dx %d dy %d from %p to %p \n",
							current_boxes[0].x1, current_boxes[0].y1,
							current_boxes[0].x2, current_boxes[0].y2,
							dx, dy, src_pixmap, dst_pixmap);

					ok = __glamor_copy_n_to_n(src, dst, gc, current_boxes,
								  n_current_boxes, dx, dy, reverse,
								  upsidedown, bitplane, closure);

				}
				RegionDestroy(clipped_dst_regions[i].region);
			}
		if (n_dst_region == 0)
			ok = TRUE;
		free(clipped_dst_regions);
	} else {
		ok = __glamor_copy_n_to_n(src, dst, gc, box, nbox, dx, dy,
					  reverse, upsidedown, bitplane,
					  closure);
	}

fail:
	RegionUninit(&region);
fail_noregion:
	dispatch = glamor_get_dispatch(glamor_priv);
	glamor_set_alu(dispatch, GXcopy);
	glamor_put_dispatch(glamor_priv);

	if (ok)
		return TRUE;
fall_back:
	if (!fallback
	    && glamor_ddx_fallback_check_pixmap(src)
	    && glamor_ddx_fallback_check_pixmap(dst))
		goto done;

	if (src_pixmap_priv->type == GLAMOR_DRM_ONLY
	    || dst_pixmap_priv->type == GLAMOR_DRM_ONLY) {
		LogMessage(X_WARNING,
			   "Access a DRM only pixmap is not allowed within glamor.\n");
		return TRUE;
	}
	glamor_report_delayed_fallbacks(src->pScreen);
	glamor_report_delayed_fallbacks(dst->pScreen);

	glamor_fallback("from %p to %p (%c,%c)\n", src, dst,
			glamor_get_drawable_location(src),
			glamor_get_drawable_location(dst));

	if (glamor_prepare_access(dst, GLAMOR_ACCESS_RW) &&
	    glamor_prepare_access(src, GLAMOR_ACCESS_RO) &&
	    glamor_prepare_access_gc(gc)) {
		fbCopyNtoN(src, dst, gc, box, nbox,
			   dx, dy, reverse, upsidedown, bitplane, closure);
	}
	glamor_finish_access_gc(gc);
	glamor_finish_access(src);
	glamor_finish_access(dst);
	ok = TRUE;

      done:
	glamor_clear_delayed_fallbacks(src->pScreen);
	glamor_clear_delayed_fallbacks(dst->pScreen);
	return ok;
}
Exemple #14
0
RegionPtr
rdpCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
            int srcx, int srcy, int w, int h, int dstx, int dsty)
{
    RegionPtr rv;
    RegionRec clip_reg;
    RegionRec box_reg;
    RegionRec reg1;
    int num_clips;
    int cd;
    int j;
    int can_do_screen_blt;
    int got_id;
    int dirty_type;
    int post_process;
    int reset_surface;
    struct image_data id;
    BoxRec box;
    BoxPtr pbox;
    PixmapPtr pSrcPixmap;
    PixmapPtr pDstPixmap;
    rdpPixmapRec *pSrcPriv;
    rdpPixmapRec *pDstPriv;
    rdpPixmapRec *pDirtyPriv;
    WindowPtr pDstWnd;
    WindowPtr pSrcWnd;

    LLOGLN(10, ("rdpCopyArea: x %d y %d w %d h %d", dstx, dsty, w, h));

    if (pSrc->type == DRAWABLE_WINDOW)
    {
        pSrcWnd = (WindowPtr)pSrc;

        if (pSrcWnd->viewable)
        {
            rdpup_check_dirty_screen(&g_screenPriv);

            if (pDst->type == DRAWABLE_WINDOW)
            {
                pDstWnd = (WindowPtr)pDst;

                if (pDstWnd->viewable)
                {
                    can_do_screen_blt = pGC->alu == GXcopy;

                    if (can_do_screen_blt)
                    {
                        return rdpCopyAreaWndToWnd(pSrcWnd, pDstWnd, pGC,
                                                   srcx, srcy, w, h, dstx, dsty);
                    }
                }
            }
            else if (pDst->type == DRAWABLE_PIXMAP)
            {
                pDstPixmap = (PixmapPtr)pDst;
                pDstPriv = GETPIXPRIV(pDstPixmap);

                if (xrdp_is_os(pDstPixmap, pDstPriv))
                {
                    can_do_screen_blt = pGC->alu == GXcopy;

                    if (can_do_screen_blt)
                    {
                        rdpup_check_dirty(pDstPixmap, pDstPriv);
                        return rdpCopyAreaWndToPixmap(pSrcWnd, pDstPixmap, pDstPriv, pGC,
                                                      srcx, srcy, w, h, dstx, dsty);
                    }
                }
                else
                {
                    LLOGLN(10, ("rdpCopyArea: 1"));
                }
            }
        }
    }

    if (pSrc->type == DRAWABLE_PIXMAP)
    {
        pSrcPixmap = (PixmapPtr)pSrc;
        pSrcPriv = GETPIXPRIV(pSrcPixmap);

        if (xrdp_is_os(pSrcPixmap, pSrcPriv))
        {
            if (pDst->type == DRAWABLE_WINDOW)
            {
                pDstWnd = (WindowPtr)pDst;

                if (pDstWnd->viewable)
                {
                    rdpup_check_dirty_screen(&g_screenPriv);
                    rdpup_check_dirty(pSrcPixmap, pSrcPriv);
                    return rdpCopyAreaPixmapToWnd(pSrcPixmap, pSrcPriv, pDstWnd, pGC,
                                                  srcx, srcy, w, h, dstx, dsty);
                }
            }
            else if (pDst->type == DRAWABLE_PIXMAP)
            {
                pDstPixmap = (PixmapPtr)pDst;
                pDstPriv = GETPIXPRIV(pDstPixmap);

                if (xrdp_is_os(pDstPixmap, pDstPriv))
                {
                    if (g_can_do_pix_to_pix)
                    {
                        rdpup_check_dirty(pSrcPixmap, pSrcPriv);
                        rdpup_check_dirty(pDstPixmap, pDstPriv);
                        return rdpCopyAreaPixmapToPixmap(pSrcPixmap, pSrcPriv,
                                                         pDstPixmap, pDstPriv,
                                                         pGC, srcx, srcy, w, h,
                                                         dstx, dsty);
                    }
                }
                else
                {
                    LLOGLN(10, ("rdpCopyArea: 4"));
                }
            }
        }
        else
        {
            LLOGLN(10, ("rdpCopyArea: 2"));
        }
    }

    /* do original call */
    rv = rdpCopyAreaOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);

    dirty_type = 0;
    pDirtyPriv = 0;
    post_process = 0;
    reset_surface = 0;
    got_id = 0;

    if (pDst->type == DRAWABLE_PIXMAP)
    {
        pDstPixmap = (PixmapPtr)pDst;
        pDstPriv = GETPIXPRIV(pDstPixmap);

        if (xrdp_is_os(pDstPixmap, pDstPriv))
        {
            post_process = 1;

            if (g_do_dirty_os)
            {
                LLOGLN(10, ("rdpCopyArea: gettig dirty"));
                pDstPriv->is_dirty = 1;
                pDirtyPriv = pDstPriv;
                dirty_type = RDI_IMGLL;
            }
            else
            {
                rdpup_switch_os_surface(pDstPriv->rdpindex);
                reset_surface = 1;
                rdpup_get_pixmap_image_rect(pDstPixmap, &id);
                got_id = 1;
            }
        }
        else
        {
            LLOGLN(10, ("rdpCopyArea: 3"));
        }
    }
    else
    {
        if (pDst->type == DRAWABLE_WINDOW)
        {
            pDstWnd = (WindowPtr)pDst;

            if (pDstWnd->viewable)
            {
                post_process = 1;

                if (g_do_dirty_ons)
                {
                    LLOGLN(10, ("rdpCopyArea: gettig dirty"));
                    g_screenPriv.is_dirty = 1;
                    pDirtyPriv = &g_screenPriv;
                    dirty_type = RDI_IMGLL;
                }
                else
                {
                    rdpup_get_screen_image_rect(&id);
                    got_id = 1;
                }
            }
        }
    }

    if (!post_process)
    {
        return rv;
    }

    RegionInit(&clip_reg, NullBox, 0);
    cd = rdp_get_clip(&clip_reg, pDst, pGC);

    if (cd == 1)
    {
        if (dirty_type != 0)
        {
            box.x1 = pDst->x + dstx;
            box.y1 = pDst->y + dsty;
            box.x2 = box.x1 + w;
            box.y2 = box.y1 + h;
            RegionInit(&reg1, &box, 0);
            draw_item_add_img_region(pDirtyPriv, &reg1, GXcopy, dirty_type, 1);
            RegionUninit(&reg1);
        }
        else if (got_id)
        {
            rdpup_begin_update();
            rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h);
            rdpup_end_update();
        }
    }
    else if (cd == 2)
    {
        num_clips = REGION_NUM_RECTS(&clip_reg);

        if (num_clips > 0)
        {
            if (dirty_type != 0)
            {
                box.x1 = pDst->x + dstx;
                box.y1 = pDst->y + dsty;
                box.x2 = box.x1 + w;
                box.y2 = box.y1 + h;
                RegionInit(&box_reg, &box, 0);
                RegionIntersect(&clip_reg, &clip_reg, &box_reg);
                draw_item_add_img_region(pDirtyPriv, &clip_reg, GXcopy, dirty_type, 1);
                RegionUninit(&box_reg);
            }
            else if (got_id)
            {
                rdpup_begin_update();
                box.x1 = pDst->x + dstx;
                box.y1 = pDst->y + dsty;
                box.x2 = box.x1 + w;
                box.y2 = box.y1 + h;
                RegionInit(&box_reg, &box, 0);
                RegionIntersect(&clip_reg, &clip_reg, &box_reg);
                num_clips = REGION_NUM_RECTS(&clip_reg);

                if (num_clips < 10)
                {
                    for (j = num_clips - 1; j >= 0; j--)
                    {
                        box = REGION_RECTS(&clip_reg)[j];
                        rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1,
                                        box.y2 - box.y1);
                    }
                }
                else
                {
                    pbox = RegionExtents(&clip_reg);
                    rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
                                    pbox->y2 - pbox->y1);
                }

                RegionUninit(&box_reg);
                rdpup_end_update();
            }
        }
    }

    RegionUninit(&clip_reg);

    if (reset_surface)
    {
        rdpup_switch_os_surface(-1);
    }

    return rv;
}
Exemple #15
0
static FBLinearPtr
localAllocateOffscreenLinear(ScreenPtr pScreen,
                             int length,
                             int gran,
                             MoveLinearCallbackProcPtr moveCB,
                             RemoveLinearCallbackProcPtr removeCB,
                             void *privData)
{
    FBManagerPtr offman;
    FBLinearLinkPtr link;
    FBAreaPtr area;
    FBLinearPtr linear = NULL;
    BoxPtr extents;
    int w, h, pitch;

    offman = (FBManagerPtr) dixLookupPrivate(&pScreen->devPrivates,
                                             xf86FBScreenKey);

    /* Try to allocate from linear memory first...... */
    DebugF("ALLOCATING LINEAR\n");
    if ((linear = AllocateLinear(offman, length, gran, privData)))
        return linear;

    DebugF("NOPE, ALLOCATING AREA\n");

    if (!(link = malloc(sizeof(FBLinearLink))))
        return NULL;

    /* No linear available, so try and pinch some from the XY areas */
    extents = RegionExtents(offman->InitialBoxes);
    pitch = extents->x2 - extents->x1;

    if (gran > 1) {
        if (gran > pitch) {
            /* we can't match the specified alignment with XY allocations */
            free(link);
            return NULL;
        }

        if (pitch % gran) {
            /* pitch and granularity aren't a perfect match, let's allocate
             * a bit more so we can align later on
             */
            length += gran - 1;
        }
    }

    if (length < pitch) {       /* special case */
        w = length;
        h = 1;
    }
    else {
        w = pitch;
        h = (length + pitch - 1) / pitch;
    }

    if ((area = localAllocateOffscreenArea(pScreen, w, h, gran,
                                           moveCB ? LinearMoveCBWrapper : NULL,
                                           removeCB ? LinearRemoveCBWrapper :
                                           NULL, privData))) {
        link->area = area;
        link->free = 0;
        link->next = offman->LinearAreas;
        offman->LinearAreas = link;
        linear = &(link->linear);
        linear->pScreen = pScreen;
        linear->size = h * w;
        linear->offset = (pitch * area->box.y1) + area->box.x1;
        if (gran > 1)
            linear->offset = ((linear->offset + gran - 1) / gran) * gran;
        linear->granularity = gran;
        linear->MoveLinearCallback = moveCB;
        linear->RemoveLinearCallback = removeCB;
        linear->devPrivate.ptr = privData;
    }
    else
        free(link);

    DumpDebug(offman->LinearAreas);

    return linear;
}
Exemple #16
0
RegionPtr rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
		int srcx, int srcy, int w, int h, int dstx, int dsty, unsigned long bitPlane)
{
	RegionPtr rv;
	RegionRec clip_reg;
	RegionRec box_reg;
	int cd;
	int num_clips;
	int j;
	int post_process;
	BoxRec box;
	BoxPtr pbox;
	WindowPtr pDstWnd;
	PixmapPtr pDstPixmap;
	rdpPixmapRec *pDstPriv;

	LLOGLN(10, ("rdpCopyPlane:"));

	/* do original call */
	rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, bitPlane);

	post_process = 0;

	if (pDst->type == DRAWABLE_PIXMAP)
	{
		pDstPixmap = (PixmapPtr) pDst;
		pDstPriv = GETPIXPRIV(pDstPixmap);
	}
	else
	{
		if (pDst->type == DRAWABLE_WINDOW)
		{
			pDstWnd = (WindowPtr) pDst;

			if (pDstWnd->viewable)
			{
				post_process = 1;
			}
		}
	}

	if (!post_process)
		return rv;

	RegionInit(&clip_reg, NullBox, 0);
	cd = rdp_get_clip(&clip_reg, pDst, pGC);

	if (cd == 1)
	{
		rdp_send_area_update(pDst->x + dstx, pDst->y + dsty, w, h);
	}
	else if (cd == 2)
	{
		num_clips = REGION_NUM_RECTS(&clip_reg);

		if (num_clips > 0)
		{
			box.x1 = pDst->x + dstx;
			box.y1 = pDst->y + dsty;
			box.x2 = box.x1 + w;
			box.y2 = box.y1 + h;
			RegionInit(&box_reg, &box, 0);
			RegionIntersect(&clip_reg, &clip_reg, &box_reg);
			num_clips = REGION_NUM_RECTS(&clip_reg);

			if (num_clips < 10)
			{
				for (j = num_clips - 1; j >= 0; j--)
				{
					box = REGION_RECTS(&clip_reg)[j];
					rdp_send_area_update(box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
				}
			}
			else
			{
				pbox = RegionExtents(&clip_reg);
				rdp_send_area_update(pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
			}

			RegionUninit(&box_reg);
		}
	}

	RegionUninit(&clip_reg);

	return rv;
}
Exemple #17
0
Bool
miMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, WindowPtr *ppLayerWin)
{
    BoxPtr box;
    WindowPtr pChild, pLast;
    Bool anyMarked = FALSE;
    MarkWindowProcPtr MarkWindow = pWin->drawable.pScreen->MarkWindow;

    /* single layered systems are easy */
    if (ppLayerWin)
        *ppLayerWin = pWin;

    if (pWin == pFirst) {
        /* Blindly mark pWin and all of its inferiors.   This is a slight
         * overkill if there are mapped windows that outside pWin's border,
         * but it's better than wasting time on RectIn checks.
         */
        pChild = pWin;
        while (1) {
            if (pChild->viewable) {
                if (RegionBroken(&pChild->winSize))
                    SetWinSize(pChild);
                if (RegionBroken(&pChild->borderSize))
                    SetBorderSize(pChild);
                (*MarkWindow) (pChild);
                if (pChild->firstChild) {
                    pChild = pChild->firstChild;
                    continue;
                }
            }
            while (!pChild->nextSib && (pChild != pWin))
                pChild = pChild->parent;
            if (pChild == pWin)
                break;
            pChild = pChild->nextSib;
        }
        anyMarked = TRUE;
        pFirst = pFirst->nextSib;
    }
    if ((pChild = pFirst)) {
        box = RegionExtents(&pWin->borderSize);
        pLast = pChild->parent->lastChild;
        while (1) {
            if (pChild->viewable) {
                if (RegionBroken(&pChild->winSize))
                    SetWinSize(pChild);
                if (RegionBroken(&pChild->borderSize))
                    SetBorderSize(pChild);
                if (RegionContainsRect(&pChild->borderSize, box)) {
                    (*MarkWindow) (pChild);
                    anyMarked = TRUE;
                    if (pChild->firstChild) {
                        pChild = pChild->firstChild;
                        continue;
                    }
                }
            }
            while (!pChild->nextSib && (pChild != pLast))
                pChild = pChild->parent;
            if (pChild == pLast)
                break;
            pChild = pChild->nextSib;
        }
    }
    if (anyMarked)
        (*MarkWindow) (pWin->parent);
    return anyMarked;
}
Exemple #18
0
RegionPtr
miHandleExposures(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
                  GCPtr pGC, int srcx, int srcy, int width, int height,
                  int dstx, int dsty)
{
    RegionPtr prgnSrcClip;      /* drawable-relative source clip */
    RegionRec rgnSrcRec;
    RegionPtr prgnDstClip;      /* drawable-relative dest clip */
    RegionRec rgnDstRec;
    BoxRec srcBox;              /* unclipped source */
    RegionRec rgnExposed;       /* exposed region, calculated source-
                                   relative, made dst relative to
                                   intersect with visible parts of
                                   dest and send events to client,
                                   and then screen relative to paint
                                   the window background
                                 */
    WindowPtr pSrcWin;
    BoxRec expBox = { 0, };
    Bool extents;

    /* avoid work if we can */
    if (!pGC->graphicsExposures && pDstDrawable->type == DRAWABLE_PIXMAP)
        return NULL;

    srcBox.x1 = srcx;
    srcBox.y1 = srcy;
    srcBox.x2 = srcx + width;
    srcBox.y2 = srcy + height;

    if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
        BoxRec TsrcBox;

        TsrcBox.x1 = srcx + pSrcDrawable->x;
        TsrcBox.y1 = srcy + pSrcDrawable->y;
        TsrcBox.x2 = TsrcBox.x1 + width;
        TsrcBox.y2 = TsrcBox.y1 + height;
        pSrcWin = (WindowPtr) pSrcDrawable;
        if (pGC->subWindowMode == IncludeInferiors) {
            prgnSrcClip = NotClippedByChildren(pSrcWin);
            if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN) {
                RegionDestroy(prgnSrcClip);
                return NULL;
            }
        }
        else {
            if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
                return NULL;
            prgnSrcClip = &rgnSrcRec;
            RegionNull(prgnSrcClip);
            RegionCopy(prgnSrcClip, &pSrcWin->clipList);
        }
        RegionTranslate(prgnSrcClip, -pSrcDrawable->x, -pSrcDrawable->y);
    }
    else {
        BoxRec box;

        if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
            (srcBox.x2 <= pSrcDrawable->width) &&
            (srcBox.y2 <= pSrcDrawable->height))
            return NULL;

        box.x1 = 0;
        box.y1 = 0;
        box.x2 = pSrcDrawable->width;
        box.y2 = pSrcDrawable->height;
        prgnSrcClip = &rgnSrcRec;
        RegionInit(prgnSrcClip, &box, 1);
        pSrcWin = NULL;
    }

    if (pDstDrawable == pSrcDrawable) {
        prgnDstClip = prgnSrcClip;
    }
    else if (pDstDrawable->type != DRAWABLE_PIXMAP) {
        if (pGC->subWindowMode == IncludeInferiors) {
            prgnDstClip = NotClippedByChildren((WindowPtr) pDstDrawable);
        }
        else {
            prgnDstClip = &rgnDstRec;
            RegionNull(prgnDstClip);
            RegionCopy(prgnDstClip, &((WindowPtr) pDstDrawable)->clipList);
        }
        RegionTranslate(prgnDstClip, -pDstDrawable->x, -pDstDrawable->y);
    }
    else {
        BoxRec box;

        box.x1 = 0;
        box.y1 = 0;
        box.x2 = pDstDrawable->width;
        box.y2 = pDstDrawable->height;
        prgnDstClip = &rgnDstRec;
        RegionInit(prgnDstClip, &box, 1);
    }

    /* drawable-relative source region */
    RegionInit(&rgnExposed, &srcBox, 1);

    /* now get the hidden parts of the source box */
    RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);

    /* move them over the destination */
    RegionTranslate(&rgnExposed, dstx - srcx, dsty - srcy);

    /* intersect with visible areas of dest */
    RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);

    /* intersect with client clip region. */
    if (pGC->clientClip)
        RegionIntersect(&rgnExposed, &rgnExposed, pGC->clientClip);

    /*
     * If we have LOTS of rectangles, we decide to take the extents
     * and force an exposure on that.  This should require much less
     * work overall, on both client and server.  This is cheating, but
     * isn't prohibited by the protocol ("spontaneous combustion" :-)
     * for windows.
     */
    extents = pGC->graphicsExposures &&
        (RegionNumRects(&rgnExposed) > RECTLIMIT) &&
        (pDstDrawable->type != DRAWABLE_PIXMAP);
    if (pSrcWin) {
        RegionPtr region;

        if (!(region = wClipShape(pSrcWin)))
            region = wBoundingShape(pSrcWin);
        /*
         * If you try to CopyArea the extents of a shaped window, compacting the
         * exposed region will undo all our work!
         */
        if (extents && pSrcWin && region &&
            (RegionContainsRect(region, &srcBox) != rgnIN))
            extents = FALSE;
    }
    if (extents) {
        expBox = *RegionExtents(&rgnExposed);
        RegionReset(&rgnExposed, &expBox);
    }
    if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
        (((WindowPtr) pDstDrawable)->backgroundState != None)) {
        WindowPtr pWin = (WindowPtr) pDstDrawable;

        /* make the exposed area screen-relative */
        RegionTranslate(&rgnExposed, pDstDrawable->x, pDstDrawable->y);

        if (extents) {
            /* PaintWindow doesn't clip, so we have to */
            RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
        }
        pDstDrawable->pScreen->PaintWindow((WindowPtr) pDstDrawable,
                                           &rgnExposed, PW_BACKGROUND);

        if (extents) {
            RegionReset(&rgnExposed, &expBox);
        }
        else
            RegionTranslate(&rgnExposed, -pDstDrawable->x, -pDstDrawable->y);
    }
    if (prgnDstClip == &rgnDstRec) {
        RegionUninit(prgnDstClip);
    }
    else if (prgnDstClip != prgnSrcClip) {
        RegionDestroy(prgnDstClip);
    }

    if (prgnSrcClip == &rgnSrcRec) {
        RegionUninit(prgnSrcClip);
    }
    else {
        RegionDestroy(prgnSrcClip);
    }

    if (pGC->graphicsExposures) {
        /* don't look */
        RegionPtr exposed = RegionCreate(NullBox, 0);

        *exposed = rgnExposed;
        return exposed;
    }
    else {
        RegionUninit(&rgnExposed);
        return NULL;
    }
}
Exemple #19
0
RegionPtr
rdpCopyPlane(DrawablePtr pSrc, DrawablePtr pDst,
             GCPtr pGC, int srcx, int srcy, int w, int h,
             int dstx, int dsty, unsigned long bitPlane)
{
  RegionPtr rv;
  RegionRec clip_reg;
  RegionRec box_reg;
  int cd;
  int num_clips;
  int j;
  int got_id;
  BoxRec box;
  BoxPtr pbox;
  struct image_data id;
  WindowPtr pDstWnd;
  PixmapPtr pDstPixmap;
  rdpPixmapRec* pDstPriv;

  LLOGLN(10, ("rdpCopyPlane:"));

  /* do original call */
  rv = rdpCopyPlaneOrg(pSrc, pDst, pGC, srcx, srcy, w, h,
                       dstx, dsty, bitPlane);
  got_id = 0;
  if (pDst->type == DRAWABLE_PIXMAP)
  {
    pDstPixmap = (PixmapPtr)pDst;
    pDstPriv = GETPIXPRIV(pDstPixmap);
    if (XRDP_IS_OS(pDstPriv))
    {
      rdpup_switch_os_surface(pDstPriv->rdpindex);
      rdpup_get_pixmap_image_rect(pDstPixmap, &id);
      got_id = 1;
    }
  }
  else
  {
    if (pDst->type == DRAWABLE_WINDOW)
    {
      pDstWnd = (WindowPtr)pDst;
      if (pDstWnd->viewable)
      {
        rdpup_get_screen_image_rect(&id);
        got_id = 1;
      }
    }
  }
  if (!got_id)
  {
    return rv;
  }

  RegionInit(&clip_reg, NullBox, 0);
  cd = rdp_get_clip(&clip_reg, pDst, pGC);
  if (cd == 1)
  {
    rdpup_begin_update();
    rdpup_send_area(&id, pDst->x + dstx, pDst->y + dsty, w, h);
    rdpup_end_update();
  }
  else if (cd == 2)
  {
    num_clips = REGION_NUM_RECTS(&clip_reg);
    if (num_clips > 0)
    {
      rdpup_begin_update();
      box.x1 = pDst->x + dstx;
      box.y1 = pDst->y + dsty;
      box.x2 = box.x1 + w;
      box.y2 = box.y1 + h;
      RegionInit(&box_reg, &box, 0);
      RegionIntersect(&clip_reg, &clip_reg, &box_reg);
      num_clips = REGION_NUM_RECTS(&clip_reg);
      if (num_clips < 10)
      {
        for (j = num_clips - 1; j >= 0; j--)
        {
          box = REGION_RECTS(&clip_reg)[j];
          rdpup_send_area(&id, box.x1, box.y1, box.x2 - box.x1, box.y2 - box.y1);
        }
      }
      else
      {
        pbox = RegionExtents(&clip_reg);
        rdpup_send_area(&id, pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
                        pbox->y2 - pbox->y1);
      }
      RegionUninit(&box_reg);
      rdpup_end_update();
    }
  }
  RegionUninit(&clip_reg);
  return rv;
}
Exemple #20
0
static void
cwCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;

    SCREEN_PROLOGUE(pScreen, CopyWindow);

    if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) {
	(*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
    } else {
	GCPtr	    pGC;
	BoxPtr	    pExtents;
	int	    x_off, y_off;
	int	    dx, dy;
	PixmapPtr   pBackingPixmap;
	RegionPtr   pClip;
	int	    src_x, src_y, dst_x, dst_y, w, h;

	dx = ptOldOrg.x - pWin->drawable.x;
	dy = ptOldOrg.y - pWin->drawable.y;

	pExtents = RegionExtents(prgnSrc);

	pBackingPixmap = (PixmapPtr) cwGetBackingDrawable((DrawablePtr)pWin,
							  &x_off, &y_off);

	src_x = pExtents->x1 - pBackingPixmap->screen_x;
	src_y = pExtents->y1 - pBackingPixmap->screen_y;
	w = pExtents->x2 - pExtents->x1;
	h = pExtents->y2 - pExtents->y1;
	dst_x = src_x - dx;
	dst_y = src_y - dy;
			       
	/* Translate region (as required by API) */
	RegionTranslate(prgnSrc, -dx, -dy);
	
	pGC = GetScratchGC(pBackingPixmap->drawable.depth, pScreen);
	/*
	 * Copy region to GC as clip, aligning as dest clip
	 */
	pClip = RegionCreate(NULL, 0);
	RegionIntersect(pClip, &pWin->borderClip, prgnSrc);
	RegionTranslate(pClip,
			 -pBackingPixmap->screen_x,
			 -pBackingPixmap->screen_y);
	
	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0);

	ValidateGC(&pBackingPixmap->drawable, pGC);

	(*pGC->ops->CopyArea) (&pBackingPixmap->drawable,
			       &pBackingPixmap->drawable, pGC,
			       src_x, src_y, w, h, dst_x, dst_y);

	(*pGC->funcs->DestroyClip) (pGC);

	FreeScratchGC(pGC);
    }
	
    SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow);
}
Exemple #21
0
static void
exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
             DDXPointPtr ppt, int *pwidth, int fSorted)
{
    ScreenPtr pScreen = pDrawable->pScreen;

    ExaScreenPriv(pScreen);
    RegionPtr pClip = fbGetCompositeClip(pGC);
    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPixmap);
    BoxPtr pextent, pbox;
    int nbox;
    int extentX1, extentX2, extentY1, extentY2;
    int fullX1, fullX2, fullY1;
    int partX1, partX2;
    int off_x, off_y;

    if (pExaScr->fallback_counter ||
        pExaScr->swappedOut ||
        pGC->fillStyle != FillSolid || pExaPixmap->accel_blocked) {
        ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted);
        return;
    }

    if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[1];

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = NULL;

        exaDoMigration(pixmaps, 1, TRUE);
    }

    if (!(pPixmap = exaGetOffscreenPixmap(pDrawable, &off_x, &off_y)) ||
        !(*pExaScr->info->PrepareSolid) (pPixmap,
                                         pGC->alu,
                                         pGC->planemask, pGC->fgPixel)) {
        ExaCheckFillSpans(pDrawable, pGC, n, ppt, pwidth, fSorted);
        return;
    }

    pextent = RegionExtents(pClip);
    extentX1 = pextent->x1;
    extentY1 = pextent->y1;
    extentX2 = pextent->x2;
    extentY2 = pextent->y2;
    while (n--) {
        fullX1 = ppt->x;
        fullY1 = ppt->y;
        fullX2 = fullX1 + (int) *pwidth;
        ppt++;
        pwidth++;

        if (fullY1 < extentY1 || extentY2 <= fullY1)
            continue;

        if (fullX1 < extentX1)
            fullX1 = extentX1;

        if (fullX2 > extentX2)
            fullX2 = extentX2;

        if (fullX1 >= fullX2)
            continue;

        nbox = RegionNumRects(pClip);
        if (nbox == 1) {
            (*pExaScr->info->Solid) (pPixmap,
                                     fullX1 + off_x, fullY1 + off_y,
                                     fullX2 + off_x, fullY1 + 1 + off_y);
        }
        else {
            pbox = RegionRects(pClip);
            while (nbox--) {
                if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) {
                    partX1 = pbox->x1;
                    if (partX1 < fullX1)
                        partX1 = fullX1;
                    partX2 = pbox->x2;
                    if (partX2 > fullX2)
                        partX2 = fullX2;
                    if (partX2 > partX1) {
                        (*pExaScr->info->Solid) (pPixmap,
                                                 partX1 + off_x, fullY1 + off_y,
                                                 partX2 + off_x,
                                                 fullY1 + 1 + off_y);
                    }
                }
                pbox++;
            }
        }
    }
    (*pExaScr->info->DoneSolid) (pPixmap);
    exaMarkSync(pScreen);
}
Exemple #22
0
static int
ProcShapeQueryExtents(ClientPtr client)
{
    REQUEST(xShapeQueryExtentsReq);
    WindowPtr pWin;
    xShapeQueryExtentsReply rep;
    BoxRec extents, *pExtents;
    int rc;
    RegionPtr region;

    REQUEST_SIZE_MATCH(xShapeQueryExtentsReq);
    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    if (rc != Success)
        return rc;
    memset(&rep, 0, sizeof(xShapeQueryExtentsReply));
    rep.type = X_Reply;
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
    rep.boundingShaped = (wBoundingShape(pWin) != 0);
    rep.clipShaped = (wClipShape(pWin) != 0);
    if ((region = wBoundingShape(pWin))) {
        /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
        pExtents = RegionExtents(region);
        extents = *pExtents;
    }
    else {
        extents.x1 = -wBorderWidth(pWin);
        extents.y1 = -wBorderWidth(pWin);
        extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
        extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
    }
    rep.xBoundingShape = extents.x1;
    rep.yBoundingShape = extents.y1;
    rep.widthBoundingShape = extents.x2 - extents.x1;
    rep.heightBoundingShape = extents.y2 - extents.y1;
    if ((region = wClipShape(pWin))) {
        /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
        pExtents = RegionExtents(region);
        extents = *pExtents;
    }
    else {
        extents.x1 = 0;
        extents.y1 = 0;
        extents.x2 = pWin->drawable.width;
        extents.y2 = pWin->drawable.height;
    }
    rep.xClipShape = extents.x1;
    rep.yClipShape = extents.y1;
    rep.widthClipShape = extents.x2 - extents.x1;
    rep.heightClipShape = extents.y2 - extents.y1;
    if (client->swapped) {
        swaps(&rep.sequenceNumber);
        swapl(&rep.length);
        swaps(&rep.xBoundingShape);
        swaps(&rep.yBoundingShape);
        swaps(&rep.widthBoundingShape);
        swaps(&rep.heightBoundingShape);
        swaps(&rep.xClipShape);
        swaps(&rep.yClipShape);
        swaps(&rep.widthClipShape);
        swaps(&rep.heightClipShape);
    }
    WriteToClient(client, sizeof(xShapeQueryExtentsReply), (char *) &rep);
    return Success;
}
Exemple #23
0
int
XAAGetRectClipBoxes(GCPtr pGC,
                    BoxPtr pboxClippedBase,
                    int nrectFill, xRectangle *prectInit)
{
    int Right, Bottom;
    BoxPtr pextent, pboxClipped = pboxClippedBase;
    xRectangle *prect = prectInit;
    RegionPtr prgnClip = pGC->pCompositeClip;

    if (RegionNumRects(prgnClip) == 1) {
        pextent = RegionRects(prgnClip);
        while (nrectFill--) {
            pboxClipped->x1 = max(pextent->x1, prect->x);
            pboxClipped->y1 = max(pextent->y1, prect->y);

            Right = (int) prect->x + (int) prect->width;
            pboxClipped->x2 = min(pextent->x2, Right);

            Bottom = (int) prect->y + (int) prect->height;
            pboxClipped->y2 = min(pextent->y2, Bottom);

            prect++;
            if ((pboxClipped->x1 < pboxClipped->x2) &&
                (pboxClipped->y1 < pboxClipped->y2)) {
                pboxClipped++;
            }
        }
    }
    else {
        pextent = RegionExtents(prgnClip);
        while (nrectFill--) {
            int n;
            BoxRec box, *pbox;

            box.x1 = max(pextent->x1, prect->x);
            box.y1 = max(pextent->y1, prect->y);

            Right = (int) prect->x + (int) prect->width;
            box.x2 = min(pextent->x2, Right);

            Bottom = (int) prect->y + (int) prect->height;
            box.y2 = min(pextent->y2, Bottom);

            prect++;

            if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
                continue;

            n = RegionNumRects(prgnClip);
            pbox = RegionRects(prgnClip);

            /* clip the rectangle to each box in the clip region
               this is logically equivalent to calling Intersect()
             */
            while (n--) {
                pboxClipped->x1 = max(box.x1, pbox->x1);
                pboxClipped->y1 = max(box.y1, pbox->y1);
                pboxClipped->x2 = min(box.x2, pbox->x2);
                pboxClipped->y2 = min(box.y2, pbox->y2);
                pbox++;

                /* see if clipping left anything */
                if (pboxClipped->x1 < pboxClipped->x2 &&
                    pboxClipped->y1 < pboxClipped->y2) {
                    pboxClipped++;
                }
            }
        }
    }

    return pboxClipped - pboxClippedBase;
}
Exemple #24
0
void
SendShapeNotify(WindowPtr pWin, int which)
{
    ShapeEventPtr *pHead, pShapeEvent;
    xShapeNotifyEvent se;
    BoxRec extents;
    RegionPtr region;
    BYTE shaped;
    int rc;

    rc = dixLookupResourceByType((pointer *) &pHead, pWin->drawable.id,
                                 ShapeEventType, serverClient, DixReadAccess);
    if (rc != Success)
        return;
    switch (which) {
    case ShapeBounding:
        region = wBoundingShape(pWin);
        if (region) {
            extents = *RegionExtents(region);
            shaped = xTrue;
        }
        else {
            extents.x1 = -wBorderWidth(pWin);
            extents.y1 = -wBorderWidth(pWin);
            extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
            extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
            shaped = xFalse;
        }
        break;
    case ShapeClip:
        region = wClipShape(pWin);
        if (region) {
            extents = *RegionExtents(region);
            shaped = xTrue;
        }
        else {
            extents.x1 = 0;
            extents.y1 = 0;
            extents.x2 = pWin->drawable.width;
            extents.y2 = pWin->drawable.height;
            shaped = xFalse;
        }
        break;
    case ShapeInput:
        region = wInputShape(pWin);
        if (region) {
            extents = *RegionExtents(region);
            shaped = xTrue;
        }
        else {
            extents.x1 = -wBorderWidth(pWin);
            extents.y1 = -wBorderWidth(pWin);
            extents.x2 = pWin->drawable.width + wBorderWidth(pWin);
            extents.y2 = pWin->drawable.height + wBorderWidth(pWin);
            shaped = xFalse;
        }
        break;
    default:
        return;
    }
    for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
        se.type = ShapeNotify + ShapeEventBase;
        se.kind = which;
        se.window = pWin->drawable.id;
        se.x = extents.x1;
        se.y = extents.y1;
        se.width = extents.x2 - extents.x1;
        se.height = extents.y2 - extents.y1;
        se.time = currentTime.milliseconds;
        se.shaped = shaped;
        WriteEventsToClient(pShapeEvent->client, 1, (xEvent *) &se);
    }
}
Exemple #25
0
void
XAAClipAndRenderRects(GCPtr pGC,
                      ClipAndRenderRectsFunc BoxFunc,
                      int nrectFill, xRectangle *prect, int xorg, int yorg)
{
    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
    int Right, Bottom, MaxBoxes;
    BoxPtr pextent, pboxClipped, pboxClippedBase;

    MaxBoxes = infoRec->PreAllocSize / sizeof(BoxRec);
    pboxClippedBase = (BoxPtr) infoRec->PreAllocMem;
    pboxClipped = pboxClippedBase;

    if (RegionNumRects(pGC->pCompositeClip) == 1) {
        pextent = RegionRects(pGC->pCompositeClip);
        while (nrectFill--) {
            pboxClipped->x1 = max(pextent->x1, prect->x);
            pboxClipped->y1 = max(pextent->y1, prect->y);

            Right = (int) prect->x + (int) prect->width;
            pboxClipped->x2 = min(pextent->x2, Right);

            Bottom = (int) prect->y + (int) prect->height;
            pboxClipped->y2 = min(pextent->y2, Bottom);

            prect++;
            if ((pboxClipped->x1 < pboxClipped->x2) &&
                (pboxClipped->y1 < pboxClipped->y2)) {
                pboxClipped++;
                if (pboxClipped >= (pboxClippedBase + MaxBoxes)) {
                    (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
                    pboxClipped = pboxClippedBase;
                }
            }
        }
    }
    else {
        pextent = RegionExtents(pGC->pCompositeClip);
        while (nrectFill--) {
            int n;
            BoxRec box, *pbox;

            box.x1 = max(pextent->x1, prect->x);
            box.y1 = max(pextent->y1, prect->y);

            Right = (int) prect->x + (int) prect->width;
            box.x2 = min(pextent->x2, Right);

            Bottom = (int) prect->y + (int) prect->height;
            box.y2 = min(pextent->y2, Bottom);

            prect++;

            if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
                continue;

            n = RegionNumRects(pGC->pCompositeClip);
            pbox = RegionRects(pGC->pCompositeClip);

            /* clip the rectangle to each box in the clip region
               this is logically equivalent to calling Intersect()
             */
            while (n--) {
                pboxClipped->x1 = max(box.x1, pbox->x1);
                pboxClipped->y1 = max(box.y1, pbox->y1);
                pboxClipped->x2 = min(box.x2, pbox->x2);
                pboxClipped->y2 = min(box.y2, pbox->y2);
                pbox++;

                /* see if clipping left anything */
                if (pboxClipped->x1 < pboxClipped->x2 &&
                    pboxClipped->y1 < pboxClipped->y2) {
                    pboxClipped++;
                    if (pboxClipped >= (pboxClippedBase + MaxBoxes)) {
                        (*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
                        pboxClipped = pboxClippedBase;
                    }
                }
            }
        }
    }

    if (pboxClipped != pboxClippedBase)
        (*BoxFunc) (pGC, pboxClipped - pboxClippedBase, pboxClippedBase,
                    xorg, yorg);
}
Exemple #26
0
static void
winShadowUpdateDD (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;

  /* 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);

  /* Unlock the shadow surface, so we can blit */
  ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsShadow, NULL);
  if (FAILED (ddrval))
    {
      ErrorF ("winShadowUpdateDD - Unlock failed\n");
      return;
    }

  /*
   * 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 rectange */
	  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 = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
					    &rcDest,
					    pScreenPriv->pddsShadow,
					    &rcSrc,
					    DDBLT_WAIT,
					    NULL);
	  
	  /* 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;

      /* 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 = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary,
					&rcDest,
					pScreenPriv->pddsShadow,
					&rcSrc,
					DDBLT_WAIT,
					NULL);

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

  /* Relock the shadow surface */
  ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsShadow,
				     NULL,
				     pScreenPriv->pddsdShadow,
				     DDLOCK_WAIT,
				     NULL);
  if (FAILED (ddrval))
    {
      ErrorF ("winShadowUpdateDD - Lock failed\n");
      return;
    }

  /* Has our memory pointer changed? */
  if (pScreenInfo->pfb != pScreenPriv->pddsdShadow->lpSurface)
    {
      ErrorF ("winShadowUpdateDD - Memory location of the shadow "
	      "surface has changed, trying to update the root window "
	      "pixmap header to point to the new address.  If you get "
	      "this message and "PROJECT_NAME" freezes or crashes "
	      "after this message then send a problem report and your "
	      "%s file to " BUILDERADDR "\n", g_pszLogFile);

      /* Location of shadow framebuffer has changed */
      pScreenInfo->pfb = pScreenPriv->pddsdShadow->lpSurface;
      
      /* Update the screen pixmap */
      if (!(*pScreen->ModifyPixmapHeader)(pScreen->devPrivate,
					  pScreen->width,
					  pScreen->height,
					  pScreen->rootDepth,
					  BitsPerPixel (pScreen->rootDepth),
					  PixmapBytePad (pScreenInfo->dwStride,
							 pScreenInfo->dwBPP),
					  pScreenInfo->pfb))
	{
	  ErrorF ("winShadowUpdateDD - Bits changed, could not "
		  "notify fb.\n");
	  return;
	}
    }
}
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);
    }
}
Exemple #28
0
/* See Porting Layer Definition - p. 54 */
void
winFillSpansNativeGDI(DrawablePtr pDrawable,
                      GCPtr pGC,
                      int iSpans,
                      DDXPointPtr pPoints, int *piWidths, int fSorted)
{
    winGCPriv(pGC);
    HBITMAP hbmpOrig = NULL, hbmpOrigStipple = NULL;
    HBITMAP hPenOrig = NULL;
    HBITMAP hBitmap = NULL;
    PixmapPtr pPixmap = NULL;
    winPrivPixmapPtr pPixmapPriv = NULL;
    PixmapPtr pStipple = NULL;
    winPrivPixmapPtr pStipplePriv = NULL;
    PixmapPtr pTile = NULL;
    winPrivPixmapPtr pTilePriv = NULL;
    HDC hdcStipple = NULL, hdcTile = NULL;
    HPEN hPen = NULL;
    int iX;
    int fg, bg;
    RegionPtr pClip = pGC->pCompositeClip;
    BoxPtr pextent, pbox;
    int nbox;
    int extentX1, extentX2, extentY1, extentY2;
    int fullX1, fullX2, fullY1;
    HRGN hrgn = NULL, combined = NULL;

    nbox = RegionNumRects(pClip);
    pbox = RegionRects(pClip);

    if (!nbox)
        return;

    combined = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
    nbox--;
    pbox++;

    while (nbox--) {
        hrgn = CreateRectRgn(pbox->x1, pbox->y1, pbox->x2, pbox->y2);
        CombineRgn(combined, combined, hrgn, RGN_OR);
        DeleteObject(hrgn);
        hrgn = NULL;
        pbox++;
    }

    pextent = RegionExtents(pClip);
    extentX1 = pextent->x1;
    extentY1 = pextent->y1;
    extentX2 = pextent->x2;
    extentY2 = pextent->y2;

    /* Branch on the type of drawable we have */
    switch (pDrawable->type) {
    case DRAWABLE_PIXMAP:

        SelectClipRgn(pGCPriv->hdcMem, combined);
        DeleteObject(combined);
        combined = NULL;

        /* Get a pixmap pointer from the drawable pointer, and fetch privates  */
        pPixmap = (PixmapPtr) pDrawable;
        pPixmapPriv = winGetPixmapPriv(pPixmap);

        /* Select the drawable pixmap into memory hdc */
        hbmpOrig = SelectObject(pGCPriv->hdcMem, pPixmapPriv->hBitmap);
        if (hbmpOrig == NULL)
            FatalError("winFillSpans - DRAWABLE_PIXMAP - "
                       "SelectObject () failed on\n\tpPixmapPriv->hBitmap: "
                       "%08x\n", (unsigned int) pPixmapPriv->hBitmap);

        /* Branch on the fill type */
        switch (pGC->fillStyle) {
        case FillSolid:

            ROP16(pGCPriv->hdcMem, pGC->alu);

            if (pDrawable->depth == 1) {
                if (pGC->fgPixel == 0)
                    hPenOrig = SelectObject(pGCPriv->hdcMem,
                                            GetStockObject(BLACK_PEN));
                else
                    hPenOrig = SelectObject(pGCPriv->hdcMem,
                                            GetStockObject(WHITE_PEN));
            }
            else {
                fg = pGC->fgPixel;
                TRANSLATE_COLOR(fg);
                hPen = CreatePen(PS_SOLID, 0, fg);
                hPenOrig = SelectObject(pGCPriv->hdcMem, hPen);
            }

            while (iSpans--) {
                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                MoveToEx(pGCPriv->hdcMem, fullX1, fullY1, NULL);
                LineTo(pGCPriv->hdcMem, fullX2, fullY1);
            }

            SetROP2(pGCPriv->hdcMem, R2_COPYPEN);

            /* Give back the Pen */
            SelectObject(pGCPriv->hdcMem, hPenOrig);

            if (pDrawable->depth != 1)
                DeleteObject(hPen);
            break;

        case FillOpaqueStippled:

            pStipple = pGC->stipple;
            pStipplePriv = winGetPixmapPriv(pStipple);

            /* Create a device-dependent bitmap for the stipple */
            hBitmap = CreateDIBitmap(pGCPriv->hdcMem,
                                     (BITMAPINFOHEADER *) pStipplePriv->pbmih,
                                     CBM_INIT,
                                     pStipplePriv->pbBits,
                                     (BITMAPINFO *) pStipplePriv->pbmih,
                                     DIB_RGB_COLORS);

            /* Create a memory DC to hold the stipple */
            hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem);

            /* Select the stipple bitmap into the stipple DC */
            hbmpOrigStipple = SelectObject(hdcStipple, hBitmap);
            if (hbmpOrigStipple == NULL)
                FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - "
                           "SelectObject () failed on hbmpOrigStipple\n");

            /* Make a temporary copy of the foreground and background colors */
            bg = pGC->bgPixel;
            fg = pGC->fgPixel;

            /* Translate the depth-dependent colors to Win32 COLORREFs */
            TRANSLATE_COLOR(fg);
            TRANSLATE_COLOR(bg);
            SetTextColor(pGCPriv->hdcMem, fg);
            SetBkColor(pGCPriv->hdcMem, bg);

            while (iSpans--) {
                int width = pStipple->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pStipple->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pStipple->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pStipple->drawable.width) -
                              pStipple->drawable.width)) %
                            pStipple->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pStipple->drawable.width)
                        width = pStipple->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdcMem,
                           iX, fullY1,
                           width, 1,
                           hdcStipple,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pStipple->drawable.height) -
                             pStipple->drawable.height)) %
                           pStipple->drawable.height, g_copyROP[pGC->alu]);
                }
            }

            /* Clear the stipple HDC */
            SelectObject(hdcStipple, hbmpOrigStipple);
            DeleteDC(hdcStipple);

            /* Delete the device dependent stipple bitmap */
            DeleteObject(hBitmap);

            break;
        case FillStippled:

            pStipple = pGC->stipple;
            pStipplePriv = winGetPixmapPriv(pStipple);

            /* Create a device-dependent bitmap for the stipple */
            hBitmap = CreateDIBitmap(pGCPriv->hdcMem,
                                     (BITMAPINFOHEADER *) pStipplePriv->pbmih,
                                     CBM_INIT,
                                     pStipplePriv->pbBits,
                                     (BITMAPINFO *) pStipplePriv->pbmih,
                                     DIB_RGB_COLORS);

            /* Create a memory DC to hold the stipple */
            hdcStipple = CreateCompatibleDC(pGCPriv->hdcMem);

            /* Select the stipple bitmap into the stipple DC */
            hbmpOrigStipple = SelectObject(hdcStipple, hBitmap);
            if (hbmpOrigStipple == NULL)
                FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - "
                           "SelectObject () failed on hbmpOrigStipple\n");

            /* Make a temporary copy of the foreground and background colors */
            bg = pGC->bgPixel;
            fg = pGC->fgPixel;

            /* Translate the depth-dependent colors to Win32 COLORREFs */
            TRANSLATE_COLOR(fg);
            TRANSLATE_COLOR(bg);

            /* this is fudgy, we should only invert on the last one
             * We need to get the black/white pixels right in the
             * colormap. But yeah ! it's working.. 
             */
            if (pGC->bgPixel != -1 && pGC->fgPixel != -1) {
                SetTextColor(pGCPriv->hdcMem, fg);
                SetBkColor(pGCPriv->hdcMem, bg);
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
            }
            else if (pGC->bgPixel == -1) {
                SetTextColor(pGCPriv->hdcMem, fg);
                SetBkMode(pGCPriv->hdcMem, TRANSPARENT);
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
            }
            else if (pGC->fgPixel == -1) {
                SetTextColor(pGCPriv->hdcMem, bg);
                SetBkMode(pGCPriv->hdcMem, TRANSPARENT);
#if 0
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
#endif
            }

            while (iSpans--) {
                int width = pStipple->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pStipple->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pStipple->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pStipple->drawable.width) -
                              pStipple->drawable.width)) %
                            pStipple->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pStipple->drawable.width)
                        width = pStipple->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdcMem,
                           iX, fullY1,
                           width, 1,
                           hdcStipple,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pStipple->drawable.height) -
                             pStipple->drawable.height)) %
                           pStipple->drawable.height, g_copyROP[pGC->alu]);
                }
            }

            /* Clear the stipple HDC */
            SelectObject(hdcStipple, hbmpOrigStipple);
            DeleteDC(hdcStipple);

            /* Delete the device dependent stipple bitmap */
            DeleteObject(hBitmap);

            /* Restore the background mode */
            SetBkMode(pGCPriv->hdcMem, OPAQUE);
            break;

        case FillTiled:

            /* Get a pixmap pointer from the tile pointer, and fetch privates  */
            pTile = (PixmapPtr) pGC->tile.pixmap;
            pTilePriv = winGetPixmapPriv(pTile);

            /* Create a memory DC to hold the tile */
            hdcTile = CreateCompatibleDC(pGCPriv->hdcMem);

            /* Select the tile into a DC */
            hbmpOrig = SelectObject(hdcTile, pTilePriv->hBitmap);
            if (hbmpOrig == NULL)
                FatalError("winFillSpans - DRAWABLE_PIXMAP - FillTiled - "
                           "SelectObject () failed on pTilePriv->hBitmap\n");

            while (iSpans--) {
                int width = pTile->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pTile->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pTile->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pTile->drawable.width) -
                              pTile->drawable.width)) % pTile->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pTile->drawable.width)
                        width = pTile->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdcMem,
                           iX, fullY1,
                           width, 1,
                           hdcTile,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pTile->drawable.height) -
                             pTile->drawable.height)) % pTile->drawable.height,
                           g_copyROP[pGC->alu]);
                }
            }

            /* Push the tile pixmap out of the memory HDC */
            SelectObject(hdcTile, hbmpOrig);

            /* Delete the tile */
            DeleteDC(hdcTile);
            break;

        default:
            ErrorF("winFillSpans - DRAWABLE_PIXMAP - Unknown fillStyle\n");
            break;
        }

        /* Reset clip region */
        SelectClipRgn(pGCPriv->hdcMem, NULL);

        /* Push the drawable pixmap out of the GC HDC */
        SelectObject(pGCPriv->hdcMem, hbmpOrig);
        break;

    case DRAWABLE_WINDOW:

        SelectClipRgn(pGCPriv->hdc, combined);
        DeleteObject(combined);
        combined = NULL;

        /* Branch on fill style */
        switch (pGC->fillStyle) {
        case FillSolid:

            ROP16(pGCPriv->hdc, pGC->alu);

            if (pDrawable->depth == 1) {
                if (pGC->fgPixel == 0)
                    hPenOrig = SelectObject(pGCPriv->hdc,
                                            GetStockObject(BLACK_PEN));
                else
                    hPenOrig = SelectObject(pGCPriv->hdc,
                                            GetStockObject(WHITE_PEN));
            }
            else {
                fg = pGC->fgPixel;
                TRANSLATE_COLOR(fg);
                hPen = CreatePen(PS_SOLID, 0, fg);
                hPenOrig = SelectObject(pGCPriv->hdc, hPen);
            }

            while (iSpans--) {
                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                MoveToEx(pGCPriv->hdc, fullX1, fullY1, NULL);
                LineTo(pGCPriv->hdc, fullX2, fullY1);
            }

            SetROP2(pGCPriv->hdc, R2_COPYPEN);

            /* Give back the Brush */
            SelectObject(pGCPriv->hdc, hPenOrig);

            if (pDrawable->depth != 1)
                DeleteObject(hPen);
            break;

        case FillOpaqueStippled:

            pStipple = pGC->stipple;
            pStipplePriv = winGetPixmapPriv(pStipple);

            /* Create a device-dependent bitmap for the stipple */
            hBitmap = CreateDIBitmap(pGCPriv->hdc,
                                     (BITMAPINFOHEADER *) pStipplePriv->pbmih,
                                     CBM_INIT,
                                     pStipplePriv->pbBits,
                                     (BITMAPINFO *) pStipplePriv->pbmih,
                                     DIB_RGB_COLORS);

            /* Create a memory DC to hold the stipple */
            hdcStipple = CreateCompatibleDC(pGCPriv->hdc);

            /* Select the stipple bitmap into the stipple DC */
            hbmpOrigStipple = SelectObject(hdcStipple, hBitmap);
            if (hbmpOrigStipple == NULL)
                FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - "
                           "SelectObject () failed on hbmpOrigStipple\n");

            /* Make a temporary copy of the foreground and background colors */
            bg = pGC->bgPixel;
            fg = pGC->fgPixel;

            /* Translate the depth-dependent colors to Win32 COLORREFs */
            TRANSLATE_COLOR(fg);
            TRANSLATE_COLOR(bg);
            SetTextColor(pGCPriv->hdc, fg);
            SetBkColor(pGCPriv->hdc, bg);

            while (iSpans--) {
                int width = pStipple->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pStipple->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pStipple->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pStipple->drawable.width) -
                              pStipple->drawable.width)) %
                            pStipple->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pStipple->drawable.width)
                        width = pStipple->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdc,
                           iX, fullY1,
                           width, 1,
                           hdcStipple,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pStipple->drawable.height) -
                             pStipple->drawable.height)) %
                           pStipple->drawable.height, g_copyROP[pGC->alu]);
                }
            }

            /* Clear the stipple HDC */
            SelectObject(hdcStipple, hbmpOrigStipple);
            DeleteDC(hdcStipple);

            /* Delete the device dependent stipple bitmap */
            DeleteObject(hBitmap);

            break;

        case FillStippled:
            pStipple = pGC->stipple;
            pStipplePriv = winGetPixmapPriv(pStipple);

            /* Create a device-dependent bitmap for the stipple */
            hBitmap = CreateDIBitmap(pGCPriv->hdcMem,
                                     (BITMAPINFOHEADER *) pStipplePriv->pbmih,
                                     CBM_INIT,
                                     pStipplePriv->pbBits,
                                     (BITMAPINFO *) pStipplePriv->pbmih,
                                     DIB_RGB_COLORS);

            /* Create a memory DC to hold the stipple */
            hdcStipple = CreateCompatibleDC(pGCPriv->hdc);

            /* Select the stipple bitmap into the stipple DC */
            hbmpOrigStipple = SelectObject(hdcStipple, hBitmap);
            if (hbmpOrigStipple == NULL)
                FatalError("winFillSpans () - DRAWABLE_PIXMAP - FillStippled - "
                           "SelectObject () failed on hbmpOrigStipple\n");

            /* Make a temporary copy of the foreground and background colors */
            bg = pGC->bgPixel;
            fg = pGC->fgPixel;

            /* Translate the depth-dependent colors to Win32 COLORREFs */
            TRANSLATE_COLOR(fg);
            TRANSLATE_COLOR(bg);

            /* this is fudgy, we should only invert on the last one
             * We need to get the black/white pixels right in the
             * colormap. But yeah ! it's working.. 
             */
            if (pGC->bgPixel != -1 && pGC->fgPixel != -1) {
                SetTextColor(pGCPriv->hdc, fg);
                SetBkColor(pGCPriv->hdc, bg);
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
            }
            else if (pGC->bgPixel == -1) {
                SetTextColor(pGCPriv->hdc, fg);
                SetBkMode(pGCPriv->hdc, TRANSPARENT);
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
            }
            else if (pGC->fgPixel == -1) {
                SetTextColor(pGCPriv->hdc, bg);
                SetBkMode(pGCPriv->hdc, TRANSPARENT);
#if 0
                BitBlt(hdcStipple,
                       0, 0,
                       pStipple->drawable.width, pStipple->drawable.height,
                       hdcStipple, 0, 0, 0x330008);
#endif
            }

            while (iSpans--) {
                int width = pStipple->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pStipple->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pStipple->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pStipple->drawable.width) -
                              pStipple->drawable.width)) %
                            pStipple->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pStipple->drawable.width)
                        width = pStipple->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdc,
                           iX, fullY1,
                           width, 1,
                           hdcStipple,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pStipple->drawable.height) -
                             pStipple->drawable.height)) %
                           pStipple->drawable.height, g_copyROP[pGC->alu]);
                }
            }

            /* Clear the stipple HDC */
            SelectObject(hdcStipple, hbmpOrigStipple);
            DeleteDC(hdcStipple);

            /* Delete the device dependent stipple bitmap */
            DeleteObject(hBitmap);

            /* Restore the background mode */
            SetBkMode(pGCPriv->hdc, OPAQUE);
            break;

        case FillTiled:

            /* Get a pixmap pointer from the tile pointer, and fetch privates  */
            pTile = (PixmapPtr) pGC->tile.pixmap;
            pTilePriv = winGetPixmapPriv(pTile);

            /* Select the tile into a DC */
            hbmpOrig = SelectObject(pGCPriv->hdcMem, pTilePriv->hBitmap);
            if (hbmpOrig == NULL)
                FatalError("winFillSpans - DRAWABLE_WINDOW - FillTiled - "
                           "SelectObject () failed on pTilePriv->hBitmap\n");

            while (iSpans--) {
                int width = pTile->drawable.width;

                fullX1 = pPoints->x;
                fullY1 = pPoints->y;
                fullX2 = fullX1 + (int) *piWidths;
                pPoints++;
                piWidths++;

                if (fullY1 < extentY1 || extentY2 <= fullY1)
                    continue;

                if (fullX1 < extentX1)
                    fullX1 = extentX1;
                if (fullX2 > extentX2)
                    fullX2 = extentX2;

                if (fullX1 >= fullX2)
                    continue;

                for (iX = fullX1; iX < fullX2; iX += width) {
                    int xoffset;

                    if ((iX + pTile->drawable.width) > fullX2)
                        width = fullX2 - iX;
                    else
                        width = pTile->drawable.width;

                    if (iX == fullX1)
                        xoffset =
                            (fullX1 -
                             (pDrawable->x +
                              (pGC->patOrg.x % pTile->drawable.width) -
                              pTile->drawable.width)) % pTile->drawable.width;
                    else
                        xoffset = 0;

                    if (xoffset + width > pTile->drawable.width)
                        width = pTile->drawable.width - xoffset;

                    BitBlt(pGCPriv->hdc,
                           iX, fullY1,
                           width, 1,
                           pGCPriv->hdcMem,
                           xoffset,
                           (fullY1 -
                            (pDrawable->y +
                             (pGC->patOrg.y % pTile->drawable.height) -
                             pTile->drawable.height)) % pTile->drawable.height,
                           g_copyROP[pGC->alu]);
                }
            }

            /* Push the tile pixmap out of the memory HDC */
            SelectObject(pGCPriv->hdcMem, hbmpOrig);
            break;

        default:
            ErrorF("winFillSpans - DRAWABLE_WINDOW - Unknown fillStyle\n");
            break;
        }

        /* Reset clip region */
        SelectClipRgn(pGCPriv->hdc, NULL);
        break;

    default:
        ErrorF("winFillSpans - Unknown drawable type\n");
        break;
    }
}
Exemple #29
0
static void
exaPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect)
{
    ExaScreenPriv(pDrawable->pScreen);
    RegionPtr pClip = fbGetCompositeClip(pGC);
    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);

    ExaPixmapPriv(pPixmap);
    register BoxPtr pbox;
    BoxPtr pextent;
    int extentX1, extentX2, extentY1, extentY2;
    int fullX1, fullX2, fullY1, fullY2;
    int partX1, partX2, partY1, partY2;
    int xoff, yoff;
    int xorg, yorg;
    int n;
    RegionPtr pReg = RegionFromRects(nrect, prect, CT_UNSORTED);

    /* Compute intersection of rects and clip region */
    RegionTranslate(pReg, pDrawable->x, pDrawable->y);
    RegionIntersect(pReg, pClip, pReg);

    if (!RegionNumRects(pReg)) {
        goto out;
    }

    exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);

    if (pExaScr->fallback_counter || pExaScr->swappedOut ||
        pExaPixmap->accel_blocked) {
        goto fallback;
    }

    /* For ROPs where overlaps don't matter, convert rectangles to region and
     * call exaFillRegion{Solid,Tiled}.
     */
    if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) &&
        (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear ||
         pGC->alu == GXnoop || pGC->alu == GXcopyInverted ||
         pGC->alu == GXset)) {
        if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) &&
             exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ?
                                pGC->fgPixel : pGC->tile.pixel, pGC->planemask,
                                pGC->alu, pGC->clientClip != NULL)) ||
            (pGC->fillStyle == FillTiled && !pGC->tileIsPixel &&
             exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg,
                                pGC->planemask, pGC->alu,
                                pGC->clientClip != NULL))) {
            goto out;
        }
    }

    if (pGC->fillStyle != FillSolid &&
        !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) {
        goto fallback;
    }

    if (pExaScr->do_migration) {
        ExaMigrationRec pixmaps[1];

        pixmaps[0].as_dst = TRUE;
        pixmaps[0].as_src = FALSE;
        pixmaps[0].pPix = pPixmap;
        pixmaps[0].pReg = NULL;

        exaDoMigration(pixmaps, 1, TRUE);
    }

    if (!exaPixmapHasGpuCopy(pPixmap) ||
        !(*pExaScr->info->PrepareSolid) (pPixmap,
                                         pGC->alu,
                                         pGC->planemask, pGC->fgPixel)) {
 fallback:
        ExaCheckPolyFillRect(pDrawable, pGC, nrect, prect);
        goto out;
    }

    xorg = pDrawable->x;
    yorg = pDrawable->y;

    pextent = RegionExtents(pClip);
    extentX1 = pextent->x1;
    extentY1 = pextent->y1;
    extentX2 = pextent->x2;
    extentY2 = pextent->y2;
    while (nrect--) {
        fullX1 = prect->x + xorg;
        fullY1 = prect->y + yorg;
        fullX2 = fullX1 + (int) prect->width;
        fullY2 = fullY1 + (int) prect->height;
        prect++;

        if (fullX1 < extentX1)
            fullX1 = extentX1;

        if (fullY1 < extentY1)
            fullY1 = extentY1;

        if (fullX2 > extentX2)
            fullX2 = extentX2;

        if (fullY2 > extentY2)
            fullY2 = extentY2;

        if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
            continue;
        n = RegionNumRects(pClip);
        if (n == 1) {
            (*pExaScr->info->Solid) (pPixmap,
                                     fullX1 + xoff, fullY1 + yoff,
                                     fullX2 + xoff, fullY2 + yoff);
        }
        else {
            pbox = RegionRects(pClip);
            /*
             * clip the rectangle to each box in the clip region
             * this is logically equivalent to calling Intersect(),
             * but rectangles may overlap each other here.
             */
            while (n--) {
                partX1 = pbox->x1;
                if (partX1 < fullX1)
                    partX1 = fullX1;
                partY1 = pbox->y1;
                if (partY1 < fullY1)
                    partY1 = fullY1;
                partX2 = pbox->x2;
                if (partX2 > fullX2)
                    partX2 = fullX2;
                partY2 = pbox->y2;
                if (partY2 > fullY2)
                    partY2 = fullY2;

                pbox++;

                if (partX1 < partX2 && partY1 < partY2) {
                    (*pExaScr->info->Solid) (pPixmap,
                                             partX1 + xoff, partY1 + yoff,
                                             partX2 + xoff, partY2 + yoff);
                }
            }
        }
    }
    (*pExaScr->info->DoneSolid) (pPixmap);
    exaMarkSync(pDrawable->pScreen);

 out:
    RegionUninit(pReg);
    RegionDestroy(pReg);
}
/**
 * If the pixmap is currently dirty, this copies at least the dirty area from
 * FB to system or vice versa.  Both areas must be allocated.
 */
static void
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
             Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
                               char *sys, int sys_pitch), int fallback_index,
             void (*sync) (ScreenPtr pScreen))
{
    PixmapPtr pPixmap = migrate->pPix;

    ExaPixmapPriv(pPixmap);
    RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
    RegionRec CopyReg;
    Bool save_use_gpu_copy;
    int save_pitch;
    BoxPtr pBox;
    int nbox;
    Bool access_prepared = FALSE;
    Bool need_sync = FALSE;

    /* Damaged bits are valid in current copy but invalid in other one */
    if (pExaPixmap->use_gpu_copy) {
        RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
        RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
    }
    else {
        RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
        RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
    }

    RegionEmpty(damage);

    /* Copy bits valid in source but not in destination */
    RegionNull(&CopyReg);
    RegionSubtract(&CopyReg, pValidSrc, pValidDst);

    if (migrate->as_dst) {
        ExaScreenPriv(pPixmap->drawable.pScreen);

        /* XXX: The pending damage region will be marked as damaged after the
         * operation, so it should serve as an upper bound for the region that
         * needs to be synchronized for the operation. Unfortunately, this
         * causes corruption in some cases, e.g. when starting compiz. See
         * https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
         */
        if (pExaScr->optimize_migration) {
            RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);

#if DEBUG_MIGRATE
            if (RegionNil(pending_damage)) {
                static Bool firsttime = TRUE;

                if (firsttime) {
                    ErrorF("%s: Pending damage region empty!\n", __func__);
                    firsttime = FALSE;
                }
            }
#endif

            /* Try to prevent destination valid region from growing too many
             * rects by filling it up to the extents of the union of the
             * destination valid region and the pending damage region.
             */
            if (RegionNumRects(pValidDst) > 10) {
                BoxRec box;
                BoxPtr pValidExt, pDamageExt;
                RegionRec closure;

                pValidExt = RegionExtents(pValidDst);
                pDamageExt = RegionExtents(pending_damage);

                box.x1 = min(pValidExt->x1, pDamageExt->x1);
                box.y1 = min(pValidExt->y1, pDamageExt->y1);
                box.x2 = max(pValidExt->x2, pDamageExt->x2);
                box.y2 = max(pValidExt->y2, pDamageExt->y2);

                RegionInit(&closure, &box, 0);
                RegionIntersect(&CopyReg, &CopyReg, &closure);
            }
            else
                RegionIntersect(&CopyReg, &CopyReg, pending_damage);
        }

        /* The caller may provide a region to be subtracted from the calculated
         * dirty region. This is to avoid migration of bits that don't
         * contribute to the result of the operation.
         */
        if (migrate->pReg)
            RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
    }
    else {
        /* The caller may restrict the region to be migrated for source pixmaps
         * to what's relevant for the operation.
         */
        if (migrate->pReg)
            RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
    }

    pBox = RegionRects(&CopyReg);
    nbox = RegionNumRects(&CopyReg);

    save_use_gpu_copy = pExaPixmap->use_gpu_copy;
    save_pitch = pPixmap->devKind;
    pExaPixmap->use_gpu_copy = TRUE;
    pPixmap->devKind = pExaPixmap->fb_pitch;

    while (nbox--) {
        pBox->x1 = max(pBox->x1, 0);
        pBox->y1 = max(pBox->y1, 0);
        pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
        pBox->y2 = min(pBox->y2, pPixmap->drawable.height);

        if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
            continue;

        if (!transfer || !transfer(pPixmap,
                                   pBox->x1, pBox->y1,
                                   pBox->x2 - pBox->x1,
                                   pBox->y2 - pBox->y1,
                                   (char *) (pExaPixmap->sys_ptr
                                             + pBox->y1 * pExaPixmap->sys_pitch
                                             +
                                             pBox->x1 *
                                             pPixmap->drawable.bitsPerPixel /
                                             8), pExaPixmap->sys_pitch)) {
            if (!access_prepared) {
                ExaDoPrepareAccess(pPixmap, fallback_index);
                access_prepared = TRUE;
            }
            if (fallback_index == EXA_PREPARE_DEST) {
                exaMemcpyBox(pPixmap, pBox,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
                             pPixmap->devPrivate.ptr, pPixmap->devKind);
            }
            else {
                exaMemcpyBox(pPixmap, pBox,
                             pPixmap->devPrivate.ptr, pPixmap->devKind,
                             pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
            }
        }
        else
            need_sync = TRUE;

        pBox++;
    }

    pExaPixmap->use_gpu_copy = save_use_gpu_copy;
    pPixmap->devKind = save_pitch;

    /* Try to prevent source valid region from growing too many rects by
     * removing parts of it which are also in the destination valid region.
     * Removing anything beyond that would lead to data loss.
     */
    if (RegionNumRects(pValidSrc) > 20)
        RegionSubtract(pValidSrc, pValidSrc, pValidDst);

    /* The copied bits are now valid in destination */
    RegionUnion(pValidDst, pValidDst, &CopyReg);

    RegionUninit(&CopyReg);

    if (access_prepared)
        exaFinishAccess(&pPixmap->drawable, fallback_index);
    else if (need_sync && sync)
        sync(pPixmap->drawable.pScreen);
}