2 * DIBDRV bit-blit operations
4 * Copyright 2009 Massimo Del Fedele
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 static inline void intSwap(int *a
, int *b
)
36 static inline void setRect(RECT
*r
, int x1
, int y1
, int x2
, int y2
)
44 static inline void setPoint(POINT
*p
, int x
, int y
)
50 static inline void setSize(SIZE
*sz
, int cx
, int cy
)
56 /* clips a source and destination areas to their respective clip rectangles
57 returning both source and dest modified; result is TRUE if clipping
58 leads to a non null rectangle, FALSE otherwise */
59 static BOOL
BitBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*sz
, RECT
*srcClip
, RECT
*dstClip
)
61 int xs1
, ys1
, xs2
, ys2
;
62 int xsc1
, ysc1
, xsc2
, ysc2
;
63 int xd1
, yd1
, xd2
, yd2
;
64 int xdc1
, ydc1
, xdc2
, ydc2
;
68 w
= sz
->cx
; h
= sz
->cy
;
70 /* if sizes null or negative, just return false */
74 /* extract dest area data */
80 /* extract source data */
86 /* if source clip area is not null, do first clipping on it */
89 /* extract source clipping area */
92 xsc2
= srcClip
->right
;
93 ysc2
= srcClip
->bottom
;
95 /* order clip area rectangle points */
96 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
97 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
99 /* clip on source clipping start point */
100 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; w
-= dx
; xd1
+= dx
; xs1
= xsc1
; }
101 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; h
-= dy
; yd1
+= dy
; ys1
= ysc1
; }
103 /* clip on source clipping end point */
104 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; w
-= dx
; xd2
-= dx
; xs2
= xsc2
; }
105 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; h
-= dy
; yd2
-= dy
; ys2
= ysc2
; }
107 /* if already zero area, return false */
111 /* now do clipping on destination area */
114 /* extract destination clipping area */
115 xdc1
= dstClip
->left
;
117 xdc2
= dstClip
->right
;
118 ydc2
= dstClip
->bottom
;
120 /* order clip area rectangle points */
121 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
122 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
124 /* clip on dest clipping start point */
125 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; w
-= dx
; xs1
+= dx
; xd1
= xdc1
; }
126 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; h
-= dy
; ys1
+= dy
; yd1
= ydc1
; }
128 /* clip on dest clipping end point */
129 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; w
-= dx
; xs2
-= dx
; xd2
= xdc2
; }
130 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; h
-= dy
; ys2
-= dy
; yd2
= ydc2
; }
132 /* if already zero area, return false */
137 /* sets clipped/translated points and sizes and returns TRUE */
138 ps
->x
= xs1
; ps
->y
= ys1
;
139 pd
->x
= xd1
; pd
->y
= yd1
;
140 sz
->cx
= w
; sz
->cy
= h
;
147 /* clips a source and destination areas to their respective clip rectangles
148 returning both source and dest modified; result is TRUE if clipping
149 leads to a non null rectangle, FALSE otherwise */
150 static BOOL
StretchBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*szSrc
, SIZE
*szDst
, RECT
*srcClip
, RECT
*dstClip
)
152 int xs1
, ys1
, xs2
, ys2
;
153 int xsc1
, ysc1
, xsc2
, ysc2
;
154 int xd1
, yd1
, xd2
, yd2
;
155 int xdc1
, ydc1
, xdc2
, ydc2
;
156 int ws
, hs
, wd
, hd
, dx
, dy
;
157 int mulh
, divh
, mulv
, divv
;
160 ws
= szSrc
->cx
; hs
= szSrc
->cy
;
161 wd
= szDst
->cx
; hd
= szDst
->cy
;
163 /* if sizes null or negative, just return false */
164 /* FIXME : add support for mirror stretch */
165 if(ws
<= 0 || hs
<= 0 || wd
<= 0 || hd
<= 0)
168 /* stores scaling factors from source rect to dest one */
169 mulh
= wd
; divh
= ws
;
170 mulv
= hd
; divv
= hs
;
172 /* extract dest area data */
178 /* extract source data */
184 /* if source clip area is not null, do first clipping on it */
187 /* extract source clipping area */
188 xsc1
= srcClip
->left
;
190 xsc2
= srcClip
->right
;
191 ysc2
= srcClip
->bottom
;
193 /* order clip area rectangle points */
194 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
195 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
197 /* clip on source clipping start point */
198 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; ws
-= dx
; xd1
+= MulDiv(dx
, mulh
, divh
); xs1
= xsc1
; }
199 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; hs
-= dy
; yd1
+= MulDiv(dy
, mulv
, divv
); ys1
= ysc1
; }
201 /* clip on source clipping end point */
202 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; ws
-= dx
; xd2
-= MulDiv(dx
, mulh
, divh
); xs2
= xsc2
; }
203 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; hs
-= dy
; yd2
-= MulDiv(dy
, mulv
, divv
); ys2
= ysc2
; }
205 /* if already zero area, return false */
206 if(ws
<= 0 || hs
<= 0)
211 /* now do clipping on destination area */
215 /* extract destination clipping area */
216 xdc1
= dstClip
->left
;
218 xdc2
= dstClip
->right
;
219 ydc2
= dstClip
->bottom
;
221 /* order clip area rectangle points */
222 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
223 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
225 /* clip on dest clipping start point */
226 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; wd
-= dx
; xs1
+= MulDiv(dx
, divh
, mulh
); xd1
= xdc1
; }
227 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; hd
-= dy
; ys1
+= MulDiv(dy
, divv
, mulv
); yd1
= ydc1
; }
229 /* clip on dest clipping end point */
230 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; wd
-= dx
; xs2
-= MulDiv(dx
, divh
, mulh
); xd2
= xdc2
; }
231 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; hd
-= dy
; ys2
-= MulDiv(dy
, divv
, mulv
); yd2
= ydc2
; }
233 /* if already zero area, return false */
234 if(wd
<= 0 || hd
<= 0)
241 /* sets clipped/translated points and sizes and returns TRUE */
242 ps
->x
= xs1
; ps
->y
= ys1
;
243 pd
->x
= xd1
; pd
->y
= yd1
;
244 szSrc
->cx
= ws
; szSrc
->cy
= hs
;
245 szDst
->cx
= wd
; szDst
->cy
= hd
;
251 /***********************************************************************
252 * _DIBDRV_InternalAlphaBlend
254 BOOL
_DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
255 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
256 BLENDFUNCTION blendfn
)
262 RECT dstClip
, srcClip
;
264 /* converts to device spaces */
265 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
266 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
267 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
268 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
270 /* from tests, it seems that negative coords on phys space are not allowed */
271 if(xDst
< 0 || yDst
< 0 || xSrc
< 0 || ySrc
< 0)
273 SetLastError(ERROR_INVALID_PARAMETER
);
277 /* first clip on physical DC sizes */
278 setPoint(&pd
, xDst
, yDst
);
279 setPoint(&ps
, xSrc
, ySrc
);
280 setSize(&szDst
, widthDst
, heightDst
);
281 setSize(&szSrc
, widthSrc
, heightSrc
);
282 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
285 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
286 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
289 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
292 xDst
= pd
.x
; yDst
= pd
.y
;
293 xSrc
= ps
.x
; ySrc
= ps
.y
;
294 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
295 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
297 /* then, do blitting for each dest clip area (no clipping on source) */
299 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
301 RECT
*r
= physDevDst
->regionRects
+ iRec
;
302 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
303 setPoint(&pd
, xDst
, yDst
);
304 setPoint(&ps
, xSrc
, ySrc
);
305 setSize(&szDst
, widthDst
, heightDst
);
306 setSize(&szSrc
, widthSrc
, heightSrc
);
307 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
309 if(physDevDst
->physBitmap
.funcs
->AlphaBlend(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
310 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, blendfn
))
316 /***********************************************************************
319 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
320 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
321 BLENDFUNCTION blendfn
)
325 POINT pd
= {xDst
, yDst
};
326 SIZE szDst
= {widthDst
, heightDst
};
328 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
329 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
330 xDst
, yDst
, widthDst
, heightDst
,
331 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
332 xSrc
, ySrc
, widthSrc
, heightSrc
));
334 /* if sizes are null or negative, or source positions are negatives, returns false */
335 if(widthSrc
<= 0 || heightSrc
<= 0 ||
336 widthDst
<= 0 || heightDst
<= 0)
339 SetLastError(ERROR_INVALID_PARAMETER
);
343 /* source sould be a 32 bit DIB */
346 FIXME("Null source bitmap -- shouldn't happen\n");
350 else if(!physDevSrc
->hasDIB
)
352 FIXME("DDB source bitmap -- shouldn't happen\n");
357 if(physDevDst
->hasDIB
)
359 /* DIB section selected in dest DC, use DIB Engine */
360 MAYBE(TRACE("Blending DIB->DIB\n"));
361 res
= _DIBDRV_InternalAlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
362 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
366 /* DDB selected on dest DC -- must double-convert */
367 HBITMAP tmpDIB
, stock
;
369 MAYBE(TRACE("Blending DIB->DDB\n"));
371 /* we should anyways convert dest to physical coordinates here before processing
372 in order to check its consistency -- source coords will be converted/clipped later
373 As we do a conversion to a temporary DIB for destination, we don't care about it */
374 _DIBDRV_Position_ws2ds(physDevDst
, &pd
.x
, &pd
.y
);
375 _DIBDRV_Sizes_ws2ds(physDevDst
, &szDst
.cx
, &szDst
.cy
);
377 /* test shows that negatives origins are not allowed */
378 if(pd
.x
< 0 || pd
.y
< 0)
380 SetLastError(ERROR_INVALID_PARAMETER
);
385 /* converts dest DDB onto a temporary DIB -- just the needed part */
386 /* WARNING -- that one could fail if rectangle on dest id out of range */
387 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
);
390 ERR("Couldn't convert dest DDB to DIB\n");
395 /* selects the temporary DIB into a temporary DC */
396 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
399 ERR("Couldn't create temporary DC\n");
400 DeleteObject(tmpDIB
);
404 stock
= SelectObject(tmpDC
, tmpDIB
);
407 ERR("Couldn't select temporary DIB into temporary DC\n");
409 DeleteObject(tmpDIB
);
414 /* blends source DIB onto temp DIB and re-blits onto dest DC */
415 res
= GdiAlphaBlend(tmpDC
, 0, 0, szDst
.cx
, szDst
.cy
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
417 MAYBE(TRACE("AlphaBlend failed\n"));
419 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
421 /* frees resources */
422 SelectObject(tmpDC
, stock
);
424 DeleteObject(tmpDIB
);
430 /***********************************************************************
431 * _DIBDRV_InternalBitBlt
433 BOOL
_DIBDRV_InternalBitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
434 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
435 INT xSrc
, INT ySrc
, DWORD rop
)
441 RECT dstClip
, srcClip
;
443 /* converts to device spaces */
444 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
445 _DIBDRV_Sizes_ws2ds(physDevDst
, &width
, &height
);
447 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
449 /* first clip on physical DC sizes */
450 setPoint(&pd
, xDst
, yDst
);
451 setPoint(&ps
, xSrc
, ySrc
);
452 setSize(&sz
, width
, height
);
453 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
457 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
458 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
461 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
464 xDst
= pd
.x
; yDst
= pd
.y
;
465 xSrc
= ps
.x
; ySrc
= ps
.y
;
466 width
= sz
.cx
; height
= sz
.cy
;
468 /* then, do blitting for each dest clip area (no clipping on source) */
470 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
472 RECT
*r
= physDevDst
->regionRects
+ iRec
;
473 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
474 setPoint(&pd
, xDst
, yDst
);
475 setPoint(&ps
, xSrc
, ySrc
);
476 setSize(&sz
, width
, height
);
477 if(!BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
))
479 if(!physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, pd
.x
, pd
.y
, sz
.cx
, sz
.cy
, physDevSrc
, ps
.x
, ps
.y
, rop
))
485 /***********************************************************************
487 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
488 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
489 INT xSrc
, INT ySrc
, DWORD rop
)
494 POINT pd
= {xDst
, yDst
};
495 POINT ps
= {xSrc
, ySrc
};
496 SIZE sz
= {width
, height
};
498 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, width:%d, height:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, rop:%08x\n",
499 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
500 xDst
, yDst
, width
, height
,
501 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
504 if(physDevDst
->hasDIB
)
506 /* DIB section selected in dest DC, use DIB Engine */
508 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
510 if(!physDevSrc
|| physDevSrc
->hasDIB
)
512 /* source is null or has a DIB, no need to convert anyting */
513 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
517 /* source is a DDB, must convert it to DIB */
519 /* don't clip on source */
520 res
= !BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
523 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
525 /* we must differentiate from 2 cases :
526 1) source DC is a memory DC
527 2) source DC is a device DC */
528 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
533 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
536 ERR("Couldn't select out DDB from source HDC\n");
540 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
543 ERR("Failed converting source DDB to DIB\n");
544 SelectObject(physDevSrc
->hdc
, ddb
);
548 SelectObject(physDevSrc
->hdc
, dib
);
549 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, 0, rop
);
550 SelectObject(physDevSrc
->hdc
, ddb
);
561 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
564 ERR("Failed converting source DDB tp DIB for device DC\n");
568 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
571 ERR("Failed creating temporary memory DC\n");
576 stock
= SelectObject(memHdc
, dib
);
579 ERR("Failed selecting converted DIB into temporary memory DC\n");
585 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
587 SelectObject(memHdc
, stock
);
595 else /* dest is a DDB */
597 /* DDB selected on dest DC, use X11 Driver */
598 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
600 /* source is null or has also a DDB, no need to convert anything */
601 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
602 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
606 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
612 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
613 res
= !BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
619 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
621 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
624 ERR("Couldn't select out DIB from source HDC\n");
628 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
631 ERR("Failed converting source DIB to DDB\n");
632 SelectObject(physDevSrc
->hdc
, dib
);
636 SelectObject(physDevSrc
->hdc
, ddb
);
637 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
638 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
639 SelectObject(physDevSrc
->hdc
, dib
);
648 /***********************************************************************
649 * _DIBDRV_InternalStretchBlt
651 BOOL
_DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
652 INT widthDst
, INT heightDst
, DIBDRVPHYSDEV
*physDevSrc
,
653 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
659 RECT dstClip
, srcClip
;
661 /* converts to device spaces */
662 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
663 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
666 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
667 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
670 /* first clip on physical DC sizes */
671 setPoint(&pd
, xDst
, yDst
);
672 setPoint(&ps
, xSrc
, ySrc
);
673 setSize(&szDst
, widthDst
, heightDst
);
674 setSize(&szSrc
, widthSrc
, heightSrc
);
675 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
678 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
679 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
682 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
685 xDst
= pd
.x
; yDst
= pd
.y
;
686 xSrc
= ps
.x
; ySrc
= ps
.y
;
687 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
688 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
690 /* then, do blitting for each dest clip area (no clipping on source) */
692 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
694 RECT
*r
= physDevDst
->regionRects
+ iRec
;
695 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
696 setPoint(&pd
, xDst
, yDst
);
697 setPoint(&ps
, xSrc
, ySrc
);
698 setSize(&szDst
, widthDst
, heightDst
);
699 setSize(&szSrc
, widthSrc
, heightSrc
);
700 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
702 if(physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
703 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, rop
))
709 /***********************************************************************
712 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
713 INT widthDst
, INT heightDst
,
714 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
715 INT widthSrc
, INT heightSrc
, DWORD rop
)
720 POINT pd
= {xDst
, yDst
};
721 POINT ps
= {xSrc
, ySrc
};
722 SIZE szDst
= {widthDst
, heightDst
};
723 SIZE szSrc
= {widthSrc
, heightSrc
};
725 /* if source and dest sizes match, just call BitBlt(), it's faster */
726 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
727 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
729 MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d, rop:%08x\n",
730 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
731 xDst
, yDst
, widthDst
, heightDst
,
732 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
733 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
735 if(physDevDst
->hasDIB
)
737 /* DIB section selected in dest DC, use DIB Engine */
739 if(!physDevSrc
|| physDevSrc
->hasDIB
)
741 /* source is null or has a DIB, no need to convert anyting */
742 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
746 /* source is a DDB, must convert it to DIB */
748 /* we must differentiate from 2 cases :
749 1) source DC is a memory DC
750 2) source DC is a device DC */
751 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
756 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
759 ERR("Couldn't select out DDB from source HDC\n");
763 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
766 ERR("Failed converting source DDB to DIB\n");
767 SelectObject(physDevSrc
->hdc
, ddb
);
771 SelectObject(physDevSrc
->hdc
, dib
);
772 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
773 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
774 SelectObject(physDevSrc
->hdc
, ddb
);
785 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
788 ERR("Failed converting source DDB tp DIB for device DC\n");
792 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
795 ERR("Failed creating temporary memory DC\n");
800 stock
= SelectObject(memHdc
, dib
);
803 ERR("Failed selecting converted DIB into temporary memory DC\n");
809 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
811 SelectObject(memHdc
, stock
);
819 else /* dest is a DDB */
821 /* DDB selected on dest DC, use X11 Driver */
822 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
824 /* source is null or has also a DDB, no need to convert anything */
825 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
826 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
830 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
836 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
837 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
843 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
844 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
846 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
849 ERR("Couldn't select out DIB from source HDC\n");
853 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
856 ERR("Failed converting source DIB to DDB\n");
857 SelectObject(physDevSrc
->hdc
, dib
);
861 if(!SelectObject(physDevSrc
->hdc
, ddb
))
863 ERR("Failed to select converted DDB into source HDC\n");
864 SelectObject(physDevSrc
->hdc
, dib
);
869 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
870 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
871 SelectObject(physDevSrc
->hdc
, dib
);
880 /***********************************************************************
883 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
887 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
891 /* DIB section selected in, use DIB Engine */
892 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
893 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
897 /* DDB selected in, use X11 driver */
898 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);