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 */
115 /* extract destination clipping area */
116 xdc1
= dstClip
->left
;
118 xdc2
= dstClip
->right
;
119 ydc2
= dstClip
->bottom
;
121 /* order clip area rectangle points */
122 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
123 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
125 /* clip on dest clipping start point */
126 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; w
-= dx
; xs1
+= dx
; xd1
= xdc1
; }
127 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; h
-= dy
; ys1
+= dy
; yd1
= ydc1
; }
129 /* clip on dest clipping end point */
130 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; w
-= dx
; xs2
-= dx
; xd2
= xdc2
; }
131 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; h
-= dy
; ys2
-= dy
; yd2
= ydc2
; }
133 /* if already zero area, return false */
138 /* sets clipped/translated points and sizes and returns TRUE */
139 ps
->x
= xs1
; ps
->y
= ys1
;
140 pd
->x
= xd1
; pd
->y
= yd1
;
141 sz
->cx
= w
; sz
->cy
= h
;
148 /* clips a source and destination areas to their respective clip rectangles
149 returning both source and dest modified; result is TRUE if clipping
150 leads to a non null rectangle, FALSE otherwise */
151 static BOOL
StretchBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*szSrc
, SIZE
*szDst
, RECT
*srcClip
, RECT
*dstClip
)
153 int xs1
, ys1
, xs2
, ys2
;
154 int xsc1
, ysc1
, xsc2
, ysc2
;
155 int xd1
, yd1
, xd2
, yd2
;
156 int xdc1
, ydc1
, xdc2
, ydc2
;
157 int ws
, hs
, wd
, hd
, dx
, dy
;
158 int mulh
, divh
, mulv
, divv
;
161 ws
= szSrc
->cx
; hs
= szSrc
->cy
;
162 wd
= szDst
->cx
; hd
= szDst
->cy
;
164 /* if sizes null or negative, just return false */
165 /* FIXME : add support for mirror stretch */
166 if(ws
<= 0 || hs
<= 0 || wd
<= 0 || hd
<= 0)
169 /* stores scaling factors from source rect to dest one */
170 mulh
= wd
; divh
= ws
;
171 mulv
= hd
; divv
= hs
;
173 /* extract dest area data */
179 /* extract source data */
185 /* if source clip area is not null, do first clipping on it */
188 /* extract source clipping area */
189 xsc1
= srcClip
->left
;
191 xsc2
= srcClip
->right
;
192 ysc2
= srcClip
->bottom
;
194 /* order clip area rectangle points */
195 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
196 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
198 /* clip on source clipping start point */
199 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; ws
-= dx
; xd1
+= MulDiv(dx
, mulh
, divh
); xs1
= xsc1
; }
200 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; hs
-= dy
; yd1
+= MulDiv(dy
, mulv
, divv
); ys1
= ysc1
; }
202 /* clip on source clipping end point */
203 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; ws
-= dx
; xd2
-= MulDiv(dx
, mulh
, divh
); xs2
= xsc2
; }
204 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; hs
-= dy
; yd2
-= MulDiv(dy
, mulv
, divv
); ys2
= ysc2
; }
206 /* if already zero area, return false */
207 if(ws
<= 0 || hs
<= 0)
212 /* now do clipping on destination area */
216 /* extract destination clipping area */
217 xdc1
= dstClip
->left
;
219 xdc2
= dstClip
->right
;
220 ydc2
= dstClip
->bottom
;
222 /* order clip area rectangle points */
223 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
224 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
226 /* clip on dest clipping start point */
227 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; wd
-= dx
; xs1
+= MulDiv(dx
, divh
, mulh
); xd1
= xdc1
; }
228 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; hd
-= dy
; ys1
+= MulDiv(dy
, divv
, mulv
); yd1
= ydc1
; }
230 /* clip on dest clipping end point */
231 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; wd
-= dx
; xs2
-= MulDiv(dx
, divh
, mulh
); xd2
= xdc2
; }
232 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; hd
-= dy
; ys2
-= MulDiv(dy
, divv
, mulv
); yd2
= ydc2
; }
234 /* if already zero area, return false */
235 if(wd
<= 0 || hd
<= 0)
242 /* sets clipped/translated points and sizes and returns TRUE */
243 ps
->x
= xs1
; ps
->y
= ys1
;
244 pd
->x
= xd1
; pd
->y
= yd1
;
245 szSrc
->cx
= ws
; szSrc
->cy
= hs
;
246 szDst
->cx
= wd
; szDst
->cy
= hd
;
252 /***********************************************************************
253 * _DIBDRV_InternalAlphaBlend
255 BOOL
_DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
256 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
257 BLENDFUNCTION blendfn
)
263 RECT dstClip
, srcClip
;
265 /* first clip on physical DC sizes */
266 setPoint(&pd
, xDst
, yDst
);
267 setPoint(&ps
, xSrc
, ySrc
);
268 setSize(&szDst
, widthDst
, heightDst
);
269 setSize(&szSrc
, widthSrc
, heightSrc
);
270 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
273 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
274 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
277 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
280 xDst
= pd
.x
; yDst
= pd
.y
;
281 xSrc
= ps
.x
; ySrc
= ps
.y
;
282 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
283 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
285 /* then, do blitting for each dest clip area (no clipping on source) */
287 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
289 RECT
*r
= physDevDst
->regionRects
+ iRec
;
290 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
291 setPoint(&pd
, xDst
, yDst
);
292 setPoint(&ps
, xSrc
, ySrc
);
293 setSize(&szDst
, widthDst
, heightDst
);
294 setSize(&szSrc
, widthSrc
, heightSrc
);
295 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
297 if(physDevDst
->physBitmap
.funcs
->AlphaBlend(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
298 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, blendfn
))
304 /***********************************************************************
307 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
308 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
309 BLENDFUNCTION blendfn
)
313 POINT pd
= {xDst
, yDst
};
314 POINT ps
= {xSrc
, ySrc
};
315 SIZE szDst
= {widthDst
, heightDst
};
316 SIZE szSrc
= {widthSrc
, heightSrc
};
318 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",
319 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
320 xDst
, yDst
, widthDst
, heightDst
,
321 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
322 xSrc
, ySrc
, widthSrc
, heightSrc
));
325 /* if sizes are null or negative, returns false */
326 if(widthSrc
<= 0 || heightSrc
<= 0 || widthDst
<= 0 || heightDst
<= 0)
332 /* source sould be a 32 bit DIB */
335 FIXME("Null source bitmap -- shouldn't happen\n");
339 else if(!physDevSrc
->hasDIB
)
341 FIXME("DDB source bitmap -- shouldn't happen\n");
346 if(physDevDst
->hasDIB
)
348 /* DIB section selected in dest DC, use DIB Engine */
349 MAYBE(TRACE("Blending DIB->DIB\n"));
350 res
= _DIBDRV_InternalAlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
351 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
355 /* DDB selected on dest DC -- must double-convert */
356 HBITMAP tmpDIB
, stock
;
358 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
359 MAYBE(TRACE("Blending DIB->DDB\n"));
362 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
365 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
366 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
368 /* converts dest DDB onto a temporary DIB -- just the needed part */
369 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, xDst
, yDst
, widthDst
, heightDst
);
372 ERR("Couldn't convert dest DDB to DIB\n");
377 /* selects the temporary DIB into a temporary DC */
378 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
381 ERR("Couldn't create temporary DC\n");
382 DeleteObject(tmpDIB
);
386 stock
= SelectObject(tmpDC
, tmpDIB
);
389 ERR("Couldn't select temporary DIB into temporary DC\n");
391 DeleteObject(tmpDIB
);
396 /* blends source DIB onto temp DIB and re-blits onto dest DC */
397 res
= GdiAlphaBlend(tmpDC
, 0, 0, widthDst
, heightDst
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
399 MAYBE(TRACE("AlphaBlend failed\n"));
401 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
403 /* frees resources */
404 SelectObject(tmpDC
, stock
);
406 DeleteObject(tmpDIB
);
412 /***********************************************************************
413 * _DIBDRV_InternalBitBlt
415 BOOL
_DIBDRV_InternalBitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
416 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
417 INT xSrc
, INT ySrc
, DWORD rop
)
423 RECT dstClip
, srcClip
;
425 /* first clip on physical DC sizes */
426 setPoint(&pd
, xDst
, yDst
);
427 setPoint(&ps
, xSrc
, ySrc
);
428 setSize(&sz
, width
, height
);
429 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
432 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
433 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
436 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
439 xDst
= pd
.x
; yDst
= pd
.y
;
440 xSrc
= ps
.x
; ySrc
= ps
.y
;
441 width
= sz
.cx
; height
= sz
.cy
;
443 /* then, do blitting for each dest clip area (no clipping on source) */
445 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
447 RECT
*r
= physDevDst
->regionRects
+ iRec
;
448 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
449 setPoint(&pd
, xDst
, yDst
);
450 setPoint(&ps
, xSrc
, ySrc
);
451 setSize(&sz
, width
, height
);
452 if(!BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
))
454 if(physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, pd
.x
, pd
.y
, sz
.cx
, sz
.cy
, physDevSrc
, ps
.x
, ps
.y
, rop
))
460 /***********************************************************************
462 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
463 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
464 INT xSrc
, INT ySrc
, DWORD rop
)
469 POINT pd
= {xDst
, yDst
};
470 POINT ps
= {xSrc
, ySrc
};
471 SIZE sz
= {width
, height
};
473 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",
474 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
475 xDst
, yDst
, width
, height
,
476 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
479 if(physDevDst
->hasDIB
)
481 /* DIB section selected in dest DC, use DIB Engine */
483 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
485 if(!physDevSrc
|| physDevSrc
->hasDIB
)
487 /* source is null or has a DIB, no need to convert anyting */
488 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
492 /* source is a DDB, must convert it to DIB */
494 /* don't clip on source */
495 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
498 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
500 /* we must differentiate from 2 cases :
501 1) source DC is a memory DC
502 2) source DC is a device DC */
503 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
508 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
511 ERR("Couldn't select out DDB from source HDC\n");
515 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
518 ERR("Failed converting source DDB to DIB\n");
519 SelectObject(physDevSrc
->hdc
, ddb
);
523 SelectObject(physDevSrc
->hdc
, dib
);
524 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, 0, rop
);
525 SelectObject(physDevSrc
->hdc
, ddb
);
536 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
539 ERR("Failed converting source DDB tp DIB for device DC\n");
543 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
546 ERR("Failed creating temporary memory DC\n");
551 stock
= SelectObject(memHdc
, dib
);
554 ERR("Failed selecting converted DIB into temporary memory DC\n");
560 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
562 SelectObject(memHdc
, stock
);
570 else /* dest is a DDB */
572 /* DDB selected on dest DC, use X11 Driver */
573 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
575 /* source is null or has also a DDB, no need to convert anything */
576 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
577 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
581 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
587 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
588 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
594 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
596 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
599 ERR("Couldn't select out DIB from source HDC\n");
603 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
606 ERR("Failed converting source DIB to DDB\n");
607 SelectObject(physDevSrc
->hdc
, dib
);
611 SelectObject(physDevSrc
->hdc
, ddb
);
612 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
613 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
614 SelectObject(physDevSrc
->hdc
, dib
);
623 /***********************************************************************
624 * _DIBDRV_InternalStretchBlt
626 BOOL
_DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
627 INT widthDst
, INT heightDst
, DIBDRVPHYSDEV
*physDevSrc
,
628 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
634 RECT dstClip
, srcClip
;
636 /* first clip on physical DC sizes */
637 setPoint(&pd
, xDst
, yDst
);
638 setPoint(&ps
, xSrc
, ySrc
);
639 setSize(&szDst
, widthDst
, heightDst
);
640 setSize(&szSrc
, widthSrc
, heightSrc
);
641 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
644 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
645 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
648 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
651 xDst
= pd
.x
; yDst
= pd
.y
;
652 xSrc
= ps
.x
; ySrc
= ps
.y
;
653 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
654 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
656 /* then, do blitting for each dest clip area (no clipping on source) */
658 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
660 RECT
*r
= physDevDst
->regionRects
+ iRec
;
661 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
662 setPoint(&pd
, xDst
, yDst
);
663 setPoint(&ps
, xSrc
, ySrc
);
664 setSize(&szDst
, widthDst
, heightDst
);
665 setSize(&szSrc
, widthSrc
, heightSrc
);
666 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
668 if(physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
669 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, rop
))
675 /***********************************************************************
678 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
679 INT widthDst
, INT heightDst
,
680 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
681 INT widthSrc
, INT heightSrc
, DWORD rop
)
686 POINT pd
= {xDst
, yDst
};
687 POINT ps
= {xSrc
, ySrc
};
688 SIZE szDst
= {widthDst
, heightDst
};
689 SIZE szSrc
= {widthSrc
, heightSrc
};
691 /* if source and dest sizes match, just call BitBlt(), it's faster */
692 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
693 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
695 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",
696 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
697 xDst
, yDst
, widthDst
, heightDst
,
698 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
699 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
701 if(physDevDst
->hasDIB
)
703 /* DIB section selected in dest DC, use DIB Engine */
705 if(!physDevSrc
|| physDevSrc
->hasDIB
)
707 /* source is null or has a DIB, no need to convert anyting */
708 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
712 /* source is a DDB, must convert it to DIB */
714 /* we must differentiate from 2 cases :
715 1) source DC is a memory DC
716 2) source DC is a device DC */
717 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
722 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
725 ERR("Couldn't select out DDB from source HDC\n");
729 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
732 ERR("Failed converting source DDB to DIB\n");
733 SelectObject(physDevSrc
->hdc
, ddb
);
737 SelectObject(physDevSrc
->hdc
, dib
);
738 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
739 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
740 SelectObject(physDevSrc
->hdc
, ddb
);
751 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
754 ERR("Failed converting source DDB tp DIB for device DC\n");
758 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
761 ERR("Failed creating temporary memory DC\n");
766 stock
= SelectObject(memHdc
, dib
);
769 ERR("Failed selecting converted DIB into temporary memory DC\n");
775 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
777 SelectObject(memHdc
, stock
);
785 else /* dest is a DDB */
787 /* DDB selected on dest DC, use X11 Driver */
788 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
790 /* source is null or has also a DDB, no need to convert anything */
791 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
792 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
796 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
802 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
803 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
809 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
810 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
812 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
815 ERR("Couldn't select out DIB from source HDC\n");
819 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
822 ERR("Failed converting source DIB to DDB\n");
823 SelectObject(physDevSrc
->hdc
, dib
);
827 if(!SelectObject(physDevSrc
->hdc
, ddb
))
829 ERR("Failed to select converted DDB into source HDC\n");
830 SelectObject(physDevSrc
->hdc
, dib
);
835 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
836 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
837 SelectObject(physDevSrc
->hdc
, dib
);
846 /***********************************************************************
849 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
853 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
857 /* DIB section selected in, use DIB Engine */
858 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
859 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
863 /* DDB selected in, use X11 driver */
864 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);