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 coords out of phys spaces are not allowed */
271 if(xDst
< 0 || yDst
< 0 || xSrc
< 0 || ySrc
< 0 ||
272 xDst
+ widthDst
> physDevDst
->physBitmap
->width
||
273 yDst
+ heightDst
> physDevDst
->physBitmap
->height
||
274 xSrc
+ widthSrc
> physDevSrc
->physBitmap
->width
||
275 ySrc
+ heightSrc
> physDevSrc
->physBitmap
->height
)
277 SetLastError(ERROR_INVALID_PARAMETER
);
281 /* first clip on physical DC sizes */
282 setPoint(&pd
, xDst
, yDst
);
283 setPoint(&ps
, xSrc
, ySrc
);
284 setSize(&szDst
, widthDst
, heightDst
);
285 setSize(&szSrc
, widthSrc
, heightSrc
);
286 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
289 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
290 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
293 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
296 xDst
= pd
.x
; yDst
= pd
.y
;
297 xSrc
= ps
.x
; ySrc
= ps
.y
;
298 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
299 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
301 /* then, do blitting for each dest clip area (no clipping on source) */
303 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
305 RECT
*r
= physDevDst
->regionRects
+ iRec
;
306 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
307 setPoint(&pd
, xDst
, yDst
);
308 setPoint(&ps
, xSrc
, ySrc
);
309 setSize(&szDst
, widthDst
, heightDst
);
310 setSize(&szSrc
, widthSrc
, heightSrc
);
311 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
313 if(physDevDst
->physBitmap
->funcs
->AlphaBlend(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
314 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, blendfn
))
320 /***********************************************************************
323 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
324 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
325 BLENDFUNCTION blendfn
)
329 POINT pd
= {xDst
, yDst
};
330 SIZE szDst
= {widthDst
, heightDst
};
332 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",
333 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
334 xDst
, yDst
, widthDst
, heightDst
,
335 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
336 xSrc
, ySrc
, widthSrc
, heightSrc
));
338 /* if sizes are null or negative, or source positions are negatives, returns false */
339 if(widthSrc
<= 0 || heightSrc
<= 0 ||
340 widthDst
<= 0 || heightDst
<= 0)
343 SetLastError(ERROR_INVALID_PARAMETER
);
347 /* source sould be a 32 bit DIB */
350 FIXME("Null source bitmap -- shouldn't happen\n");
354 else if(!physDevSrc
->hasDIB
)
356 FIXME("DDB source bitmap still not supported\n");
361 if(physDevDst
->hasDIB
)
363 /* DIB section selected in dest DC, use DIB Engine */
364 MAYBE(TRACE("Blending DIB->DIB\n"));
365 res
= _DIBDRV_InternalAlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
366 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
370 /* DDB selected on dest DC -- must double-convert */
371 HBITMAP tmpDIB
, stock
;
373 MAYBE(TRACE("Blending DIB->DDB\n"));
375 /* we should anyways convert dest to physical coordinates here before processing
376 in order to check its consistency -- source coords will be converted/clipped later
377 As we do a conversion to a temporary DIB for destination, we don't care about it */
378 _DIBDRV_Position_ws2ds(physDevDst
, &pd
.x
, &pd
.y
);
379 _DIBDRV_Sizes_ws2ds(physDevDst
, &szDst
.cx
, &szDst
.cy
);
381 /* test shows that negatives origins are not allowed */
382 if(pd
.x
< 0 || pd
.y
< 0)
384 SetLastError(ERROR_INVALID_PARAMETER
);
389 /* converts dest DDB onto a temporary DIB -- just the needed part */
390 /* WARNING -- that one could fail if rectangle on dest id out of range */
391 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
);
394 ERR("Couldn't convert dest DDB to DIB\n");
399 /* selects the temporary DIB into a temporary DC */
400 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
403 ERR("Couldn't create temporary DC\n");
404 DeleteObject(tmpDIB
);
408 stock
= SelectObject(tmpDC
, tmpDIB
);
411 ERR("Couldn't select temporary DIB into temporary DC\n");
413 DeleteObject(tmpDIB
);
418 /* blends source DIB onto temp DIB and re-blits onto dest DC */
419 res
= GdiAlphaBlend(tmpDC
, 0, 0, szDst
.cx
, szDst
.cy
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
421 MAYBE(TRACE("AlphaBlend failed\n"));
423 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
425 /* frees resources */
426 SelectObject(tmpDC
, stock
);
428 DeleteObject(tmpDIB
);
434 /***********************************************************************
435 * _DIBDRV_InternalBitBlt
437 BOOL
_DIBDRV_InternalBitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
438 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
439 INT xSrc
, INT ySrc
, DWORD rop
)
445 RECT dstClip
, srcClip
;
447 /* converts to device spaces */
448 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
449 _DIBDRV_Sizes_ws2ds(physDevDst
, &width
, &height
);
451 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
453 /* first clip on physical DC sizes */
454 setPoint(&pd
, xDst
, yDst
);
455 setPoint(&ps
, xSrc
, ySrc
);
456 setSize(&sz
, width
, height
);
457 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
461 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
462 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
465 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
468 xDst
= pd
.x
; yDst
= pd
.y
;
469 xSrc
= ps
.x
; ySrc
= ps
.y
;
470 width
= sz
.cx
; height
= sz
.cy
;
472 /* then, do blitting for each dest clip area (no clipping on source) */
474 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
476 RECT
*r
= physDevDst
->regionRects
+ iRec
;
477 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
478 setPoint(&pd
, xDst
, yDst
);
479 setPoint(&ps
, xSrc
, ySrc
);
480 setSize(&sz
, width
, height
);
481 if(!BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
))
483 if(!physDevDst
->physBitmap
->funcs
->BitBlt(physDevDst
, pd
.x
, pd
.y
, sz
.cx
, sz
.cy
, physDevSrc
, ps
.x
, ps
.y
, rop
))
489 /***********************************************************************
491 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
492 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
493 INT xSrc
, INT ySrc
, DWORD rop
)
498 POINT pd
= {xDst
, yDst
};
499 POINT ps
= {xSrc
, ySrc
};
500 SIZE sz
= {width
, height
};
502 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",
503 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
504 xDst
, yDst
, width
, height
,
505 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
508 if(physDevDst
->hasDIB
)
510 /* DIB section selected in dest DC, use DIB Engine */
512 RECT dstClip
= {0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
};
514 if(!physDevSrc
|| physDevSrc
->hasDIB
)
516 /* source is null or has a DIB, no need to convert anyting */
517 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
521 /* source is a DDB, must convert it to DIB */
523 /* don't clip on source */
524 res
= !BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
527 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
529 /* we must differentiate from 2 cases :
530 1) source DC is a memory DC
531 2) source DC is a device DC */
532 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
537 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
540 ERR("Couldn't select out DDB from source HDC\n");
544 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
547 ERR("Failed converting source DDB to DIB\n");
548 SelectObject(physDevSrc
->hdc
, ddb
);
552 SelectObject(physDevSrc
->hdc
, dib
);
553 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, 0, rop
);
554 SelectObject(physDevSrc
->hdc
, ddb
);
565 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
568 ERR("Failed converting source DDB tp DIB for device DC\n");
572 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
575 ERR("Failed creating temporary memory DC\n");
580 stock
= SelectObject(memHdc
, dib
);
583 ERR("Failed selecting converted DIB into temporary memory DC\n");
589 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
591 SelectObject(memHdc
, stock
);
599 else /* dest is a DDB */
601 /* DDB selected on dest DC, use X11 Driver */
602 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
604 /* source is null or has also a DDB, no need to convert anything */
605 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
606 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
610 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
616 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
};
617 res
= !BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
623 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
625 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
628 ERR("Couldn't select out DIB from source HDC\n");
632 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
635 ERR("Failed converting source DIB to DDB\n");
636 SelectObject(physDevSrc
->hdc
, dib
);
640 SelectObject(physDevSrc
->hdc
, ddb
);
641 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
642 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
643 SelectObject(physDevSrc
->hdc
, dib
);
652 /***********************************************************************
653 * _DIBDRV_InternalStretchBlt
655 BOOL
_DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
656 INT widthDst
, INT heightDst
, DIBDRVPHYSDEV
*physDevSrc
,
657 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
663 RECT dstClip
, srcClip
;
665 /* converts to device spaces */
666 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
667 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
670 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
671 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
674 /* first clip on physical DC sizes */
675 setPoint(&pd
, xDst
, yDst
);
676 setPoint(&ps
, xSrc
, ySrc
);
677 setSize(&szDst
, widthDst
, heightDst
);
678 setSize(&szSrc
, widthSrc
, heightSrc
);
679 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
682 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
683 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
686 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
689 xDst
= pd
.x
; yDst
= pd
.y
;
690 xSrc
= ps
.x
; ySrc
= ps
.y
;
691 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
692 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
694 /* then, do blitting for each dest clip area (no clipping on source) */
696 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
698 RECT
*r
= physDevDst
->regionRects
+ iRec
;
699 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
700 setPoint(&pd
, xDst
, yDst
);
701 setPoint(&ps
, xSrc
, ySrc
);
702 setSize(&szDst
, widthDst
, heightDst
);
703 setSize(&szSrc
, widthSrc
, heightSrc
);
704 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
706 if(physDevDst
->physBitmap
->funcs
->StretchBlt(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
707 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, rop
))
713 /***********************************************************************
716 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
717 INT widthDst
, INT heightDst
,
718 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
719 INT widthSrc
, INT heightSrc
, DWORD rop
)
724 POINT pd
= {xDst
, yDst
};
725 POINT ps
= {xSrc
, ySrc
};
726 SIZE szDst
= {widthDst
, heightDst
};
727 SIZE szSrc
= {widthSrc
, heightSrc
};
729 /* if source and dest sizes match, just call BitBlt(), it's faster */
730 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
731 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
733 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",
734 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
735 xDst
, yDst
, widthDst
, heightDst
,
736 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
737 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
739 if(physDevDst
->hasDIB
)
741 /* DIB section selected in dest DC, use DIB Engine */
743 if(!physDevSrc
|| physDevSrc
->hasDIB
)
745 /* source is null or has a DIB, no need to convert anyting */
746 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
750 /* source is a DDB, must convert it to DIB */
752 /* we must differentiate from 2 cases :
753 1) source DC is a memory DC
754 2) source DC is a device DC */
755 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
760 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
763 ERR("Couldn't select out DDB from source HDC\n");
767 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
770 ERR("Failed converting source DDB to DIB\n");
771 SelectObject(physDevSrc
->hdc
, ddb
);
775 SelectObject(physDevSrc
->hdc
, dib
);
776 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
777 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
778 SelectObject(physDevSrc
->hdc
, ddb
);
789 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
792 ERR("Failed converting source DDB tp DIB for device DC\n");
796 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
799 ERR("Failed creating temporary memory DC\n");
804 stock
= SelectObject(memHdc
, dib
);
807 ERR("Failed selecting converted DIB into temporary memory DC\n");
813 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
815 SelectObject(memHdc
, stock
);
823 else /* dest is a DDB */
825 /* DDB selected on dest DC, use X11 Driver */
826 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
828 /* source is null or has also a DDB, no need to convert anything */
829 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
830 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
834 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
840 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
};
841 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
847 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
848 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
850 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
853 ERR("Couldn't select out DIB from source HDC\n");
857 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
860 ERR("Failed converting source DIB to DDB\n");
861 SelectObject(physDevSrc
->hdc
, dib
);
865 if(!SelectObject(physDevSrc
->hdc
, ddb
))
867 ERR("Failed to select converted DDB into source HDC\n");
868 SelectObject(physDevSrc
->hdc
, dib
);
873 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
874 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
875 SelectObject(physDevSrc
->hdc
, dib
);
884 /***********************************************************************
887 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
891 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
895 /* DIB section selected in, use DIB Engine */
896 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
897 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
901 /* DDB selected in, use X11 driver */
902 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);