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 /* converts to device spaces */
266 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
267 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
268 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
269 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
271 /* first clip on physical DC sizes */
272 setPoint(&pd
, xDst
, yDst
);
273 setPoint(&ps
, xSrc
, ySrc
);
274 setSize(&szDst
, widthDst
, heightDst
);
275 setSize(&szSrc
, widthSrc
, heightSrc
);
276 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
279 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
280 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
283 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
286 xDst
= pd
.x
; yDst
= pd
.y
;
287 xSrc
= ps
.x
; ySrc
= ps
.y
;
288 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
289 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
291 /* then, do blitting for each dest clip area (no clipping on source) */
293 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
295 RECT
*r
= physDevDst
->regionRects
+ iRec
;
296 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
297 setPoint(&pd
, xDst
, yDst
);
298 setPoint(&ps
, xSrc
, ySrc
);
299 setSize(&szDst
, widthDst
, heightDst
);
300 setSize(&szSrc
, widthSrc
, heightSrc
);
301 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
303 if(physDevDst
->physBitmap
.funcs
->AlphaBlend(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
304 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, blendfn
))
310 /***********************************************************************
313 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
314 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
315 BLENDFUNCTION blendfn
)
319 POINT pd
= {xDst
, yDst
};
320 POINT ps
= {xSrc
, ySrc
};
321 SIZE szDst
= {widthDst
, heightDst
};
322 SIZE szSrc
= {widthSrc
, heightSrc
};
324 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",
325 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
326 xDst
, yDst
, widthDst
, heightDst
,
327 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
328 xSrc
, ySrc
, widthSrc
, heightSrc
));
330 /* if sizes are null or negative, returns false */
331 if(widthSrc
<= 0 || heightSrc
<= 0 || widthDst
<= 0 || heightDst
<= 0)
337 /* source sould be a 32 bit DIB */
340 FIXME("Null source bitmap -- shouldn't happen\n");
344 else if(!physDevSrc
->hasDIB
)
346 FIXME("DDB source bitmap -- shouldn't happen\n");
351 if(physDevDst
->hasDIB
)
353 /* DIB section selected in dest DC, use DIB Engine */
354 MAYBE(TRACE("Blending DIB->DIB\n"));
355 res
= _DIBDRV_InternalAlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
356 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
360 /* DDB selected on dest DC -- must double-convert */
361 HBITMAP tmpDIB
, stock
;
363 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
364 MAYBE(TRACE("Blending DIB->DDB\n"));
367 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
370 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
371 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
373 /* converts dest DDB onto a temporary DIB -- just the needed part */
374 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, xDst
, yDst
, widthDst
, heightDst
);
377 ERR("Couldn't convert dest DDB to DIB\n");
382 /* selects the temporary DIB into a temporary DC */
383 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
386 ERR("Couldn't create temporary DC\n");
387 DeleteObject(tmpDIB
);
391 stock
= SelectObject(tmpDC
, tmpDIB
);
394 ERR("Couldn't select temporary DIB into temporary DC\n");
396 DeleteObject(tmpDIB
);
401 /* blends source DIB onto temp DIB and re-blits onto dest DC */
402 res
= GdiAlphaBlend(tmpDC
, 0, 0, widthDst
, heightDst
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
404 MAYBE(TRACE("AlphaBlend failed\n"));
406 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
408 /* frees resources */
409 SelectObject(tmpDC
, stock
);
411 DeleteObject(tmpDIB
);
417 /***********************************************************************
418 * _DIBDRV_InternalBitBlt
420 BOOL
_DIBDRV_InternalBitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
421 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
422 INT xSrc
, INT ySrc
, DWORD rop
)
428 RECT dstClip
, srcClip
;
430 /* converts to device spaces */
431 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
432 _DIBDRV_Sizes_ws2ds(physDevDst
, &width
, &height
);
434 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
436 /* first clip on physical DC sizes */
437 setPoint(&pd
, xDst
, yDst
);
438 setPoint(&ps
, xSrc
, ySrc
);
439 setSize(&sz
, width
, height
);
440 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
443 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
444 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
447 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
450 xDst
= pd
.x
; yDst
= pd
.y
;
451 xSrc
= ps
.x
; ySrc
= ps
.y
;
452 width
= sz
.cx
; height
= sz
.cy
;
454 /* then, do blitting for each dest clip area (no clipping on source) */
456 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
458 RECT
*r
= physDevDst
->regionRects
+ iRec
;
459 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
460 setPoint(&pd
, xDst
, yDst
);
461 setPoint(&ps
, xSrc
, ySrc
);
462 setSize(&sz
, width
, height
);
463 if(!BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
))
465 if(physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, pd
.x
, pd
.y
, sz
.cx
, sz
.cy
, physDevSrc
, ps
.x
, ps
.y
, rop
))
471 /***********************************************************************
473 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
474 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
475 INT xSrc
, INT ySrc
, DWORD rop
)
480 POINT pd
= {xDst
, yDst
};
481 POINT ps
= {xSrc
, ySrc
};
482 SIZE sz
= {width
, height
};
484 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",
485 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
486 xDst
, yDst
, width
, height
,
487 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
490 if(physDevDst
->hasDIB
)
492 /* DIB section selected in dest DC, use DIB Engine */
494 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
496 if(!physDevSrc
|| physDevSrc
->hasDIB
)
498 /* source is null or has a DIB, no need to convert anyting */
499 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
503 /* source is a DDB, must convert it to DIB */
505 /* don't clip on source */
506 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
509 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
511 /* we must differentiate from 2 cases :
512 1) source DC is a memory DC
513 2) source DC is a device DC */
514 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
519 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
522 ERR("Couldn't select out DDB from source HDC\n");
526 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
529 ERR("Failed converting source DDB to DIB\n");
530 SelectObject(physDevSrc
->hdc
, ddb
);
534 SelectObject(physDevSrc
->hdc
, dib
);
535 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, 0, rop
);
536 SelectObject(physDevSrc
->hdc
, ddb
);
547 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
550 ERR("Failed converting source DDB tp DIB for device DC\n");
554 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
557 ERR("Failed creating temporary memory DC\n");
562 stock
= SelectObject(memHdc
, dib
);
565 ERR("Failed selecting converted DIB into temporary memory DC\n");
571 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
573 SelectObject(memHdc
, stock
);
581 else /* dest is a DDB */
583 /* DDB selected on dest DC, use X11 Driver */
584 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
586 /* source is null or has also a DDB, no need to convert anything */
587 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
588 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
592 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
598 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
599 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
605 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
607 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
610 ERR("Couldn't select out DIB from source HDC\n");
614 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
617 ERR("Failed converting source DIB to DDB\n");
618 SelectObject(physDevSrc
->hdc
, dib
);
622 SelectObject(physDevSrc
->hdc
, ddb
);
623 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
624 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
625 SelectObject(physDevSrc
->hdc
, dib
);
634 /***********************************************************************
635 * _DIBDRV_InternalStretchBlt
637 BOOL
_DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
638 INT widthDst
, INT heightDst
, DIBDRVPHYSDEV
*physDevSrc
,
639 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
645 RECT dstClip
, srcClip
;
647 /* converts to device spaces */
648 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
649 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
652 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
653 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
656 /* first clip on physical DC sizes */
657 setPoint(&pd
, xDst
, yDst
);
658 setPoint(&ps
, xSrc
, ySrc
);
659 setSize(&szDst
, widthDst
, heightDst
);
660 setSize(&szSrc
, widthSrc
, heightSrc
);
661 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
);
664 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
);
665 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
668 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
671 xDst
= pd
.x
; yDst
= pd
.y
;
672 xSrc
= ps
.x
; ySrc
= ps
.y
;
673 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
674 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
676 /* then, do blitting for each dest clip area (no clipping on source) */
678 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
680 RECT
*r
= physDevDst
->regionRects
+ iRec
;
681 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
682 setPoint(&pd
, xDst
, yDst
);
683 setPoint(&ps
, xSrc
, ySrc
);
684 setSize(&szDst
, widthDst
, heightDst
);
685 setSize(&szSrc
, widthSrc
, heightSrc
);
686 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
688 if(physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
689 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, rop
))
695 /***********************************************************************
698 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
699 INT widthDst
, INT heightDst
,
700 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
701 INT widthSrc
, INT heightSrc
, DWORD rop
)
706 POINT pd
= {xDst
, yDst
};
707 POINT ps
= {xSrc
, ySrc
};
708 SIZE szDst
= {widthDst
, heightDst
};
709 SIZE szSrc
= {widthSrc
, heightSrc
};
711 /* if source and dest sizes match, just call BitBlt(), it's faster */
712 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
713 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
715 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",
716 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
717 xDst
, yDst
, widthDst
, heightDst
,
718 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
719 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
721 if(physDevDst
->hasDIB
)
723 /* DIB section selected in dest DC, use DIB Engine */
725 if(!physDevSrc
|| physDevSrc
->hasDIB
)
727 /* source is null or has a DIB, no need to convert anyting */
728 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
732 /* source is a DDB, must convert it to DIB */
734 /* we must differentiate from 2 cases :
735 1) source DC is a memory DC
736 2) source DC is a device DC */
737 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
742 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
745 ERR("Couldn't select out DDB from source HDC\n");
749 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
752 ERR("Failed converting source DDB to DIB\n");
753 SelectObject(physDevSrc
->hdc
, ddb
);
757 SelectObject(physDevSrc
->hdc
, dib
);
758 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
759 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
760 SelectObject(physDevSrc
->hdc
, ddb
);
771 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
774 ERR("Failed converting source DDB tp DIB for device DC\n");
778 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
781 ERR("Failed creating temporary memory DC\n");
786 stock
= SelectObject(memHdc
, dib
);
789 ERR("Failed selecting converted DIB into temporary memory DC\n");
795 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
797 SelectObject(memHdc
, stock
);
805 else /* dest is a DDB */
807 /* DDB selected on dest DC, use X11 Driver */
808 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
810 /* source is null or has also a DDB, no need to convert anything */
811 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
812 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
816 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
822 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
823 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
829 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
830 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
832 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
835 ERR("Couldn't select out DIB from source HDC\n");
839 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
842 ERR("Failed converting source DIB to DDB\n");
843 SelectObject(physDevSrc
->hdc
, dib
);
847 if(!SelectObject(physDevSrc
->hdc
, ddb
))
849 ERR("Failed to select converted DDB into source HDC\n");
850 SelectObject(physDevSrc
->hdc
, dib
);
855 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
856 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
857 SelectObject(physDevSrc
->hdc
, dib
);
866 /***********************************************************************
869 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
873 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
877 /* DIB section selected in, use DIB Engine */
878 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
879 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
883 /* DDB selected in, use X11 driver */
884 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);