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 void CheckMapping(const char *func
, const char *s
, DIBDRVPHYSDEV
*physDev
)
36 _DIBDRV_Position_ws2ds(physDev
, &a
, &b
);
37 if(a
!= 10 || b
!= 20)
38 FIXME("%s:%s:Position(10, 20) translated to(%d, %d)\n", func
, s
, a
, b
);
40 _DIBDRV_Sizes_ws2ds(physDev
, &a
, &b
);
41 if(a
!= 10 || b
!= 20)
42 FIXME("%s:%s:sizes (10, 20) translated to(%d, %d)\n", func
, s
, a
, b
);
45 static inline void intSwap(int *a
, int *b
)
53 static inline void setRect(RECT
*r
, int x1
, int y1
, int x2
, int y2
)
61 static inline void setPoint(POINT
*p
, int x
, int y
)
67 static inline void setSize(SIZE
*sz
, int cx
, int cy
)
73 /* clips a source and destination areas to their respective clip rectangles
74 returning both source and dest modified; result is TRUE if clipping
75 leads to a non null rectangle, FALSE otherwise */
76 static BOOL
BitBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*sz
, RECT
*srcClip
, RECT
*dstClip
)
78 int xs1
, ys1
, xs2
, ys2
;
79 int xsc1
, ysc1
, xsc2
, ysc2
;
80 int xd1
, yd1
, xd2
, yd2
;
81 int xdc1
, ydc1
, xdc2
, ydc2
;
85 w
= sz
->cx
; h
= sz
->cy
;
87 /* if sizes null or negative, just return false */
91 /* extract dest area data */
97 /* extract source data */
103 /* if source clip area is not null, do first clipping on it */
106 /* extract source clipping area */
107 xsc1
= srcClip
->left
;
109 xsc2
= srcClip
->right
;
110 ysc2
= srcClip
->bottom
;
112 /* order clip area rectangle points */
113 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
114 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
116 /* clip on source clipping start point */
117 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; w
-= dx
; xd1
+= dx
; xs1
= xsc1
; }
118 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; h
-= dy
; yd1
+= dy
; ys1
= ysc1
; }
120 /* clip on source clipping end point */
121 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; w
-= dx
; xd2
-= dx
; xs2
= xsc2
; }
122 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; h
-= dy
; yd2
-= dy
; ys2
= ysc2
; }
124 /* if already zero area, return false */
128 /* now do clipping on destination area */
131 /* extract destination clipping area */
132 xdc1
= dstClip
->left
;
134 xdc2
= dstClip
->right
;
135 ydc2
= dstClip
->bottom
;
137 /* order clip area rectangle points */
138 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
139 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
141 /* clip on dest clipping start point */
142 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; w
-= dx
; xs1
+= dx
; xd1
= xdc1
; }
143 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; h
-= dy
; ys1
+= dy
; yd1
= ydc1
; }
145 /* clip on dest clipping end point */
146 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; w
-= dx
; xs2
-= dx
; xd2
= xdc2
; }
147 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; h
-= dy
; ys2
-= dy
; yd2
= ydc2
; }
149 /* if already zero area, return false */
154 /* sets clipped/translated points and sizes and returns TRUE */
155 ps
->x
= xs1
; ps
->y
= ys1
;
156 pd
->x
= xd1
; pd
->y
= yd1
;
157 sz
->cx
= w
; sz
->cy
= h
;
164 /* clips a source and destination areas to their respective clip rectangles
165 returning both source and dest modified; result is TRUE if clipping
166 leads to a non null rectangle, FALSE otherwise */
167 static BOOL
StretchBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*szSrc
, SIZE
*szDst
, RECT
*srcClip
, RECT
*dstClip
)
169 int xs1
, ys1
, xs2
, ys2
;
170 int xsc1
, ysc1
, xsc2
, ysc2
;
171 int xd1
, yd1
, xd2
, yd2
;
172 int xdc1
, ydc1
, xdc2
, ydc2
;
173 int ws
, hs
, wd
, hd
, dx
, dy
;
174 int mulh
, divh
, mulv
, divv
;
177 ws
= szSrc
->cx
; hs
= szSrc
->cy
;
178 wd
= szDst
->cx
; hd
= szDst
->cy
;
180 /* if sizes null or negative, just return false */
181 /* FIXME : add support for mirror stretch */
182 if(ws
<= 0 || hs
<= 0 || wd
<= 0 || hd
<= 0)
185 /* stores scaling factors from source rect to dest one */
186 mulh
= wd
; divh
= ws
;
187 mulv
= hd
; divv
= hs
;
189 /* extract dest area data */
195 /* extract source data */
201 /* if source clip area is not null, do first clipping on it */
204 /* extract source clipping area */
205 xsc1
= srcClip
->left
;
207 xsc2
= srcClip
->right
;
208 ysc2
= srcClip
->bottom
;
210 /* order clip area rectangle points */
211 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
212 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
214 /* clip on source clipping start point */
215 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; ws
-= dx
; xd1
+= MulDiv(dx
, mulh
, divh
); xs1
= xsc1
; }
216 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; hs
-= dy
; yd1
+= MulDiv(dy
, mulv
, divv
); ys1
= ysc1
; }
218 /* clip on source clipping end point */
219 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; ws
-= dx
; xd2
-= MulDiv(dx
, mulh
, divh
); xs2
= xsc2
; }
220 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; hs
-= dy
; yd2
-= MulDiv(dy
, mulv
, divv
); ys2
= ysc2
; }
222 /* if already zero area, return false */
223 if(ws
<= 0 || hs
<= 0)
228 /* now do clipping on destination area */
232 /* extract destination clipping area */
233 xdc1
= dstClip
->left
;
235 xdc2
= dstClip
->right
;
236 ydc2
= dstClip
->bottom
;
238 /* order clip area rectangle points */
239 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
240 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
242 /* clip on dest clipping start point */
243 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; wd
-= dx
; xs1
+= MulDiv(dx
, divh
, mulh
); xd1
= xdc1
; }
244 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; hd
-= dy
; ys1
+= MulDiv(dy
, divv
, mulv
); yd1
= ydc1
; }
246 /* clip on dest clipping end point */
247 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; wd
-= dx
; xs2
-= MulDiv(dx
, divh
, mulh
); xd2
= xdc2
; }
248 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; hd
-= dy
; ys2
-= MulDiv(dy
, divv
, mulv
); yd2
= ydc2
; }
250 /* if already zero area, return false */
251 if(wd
<= 0 || hd
<= 0)
258 /* sets clipped/translated points and sizes and returns TRUE */
259 ps
->x
= xs1
; ps
->y
= ys1
;
260 pd
->x
= xd1
; pd
->y
= yd1
;
261 szSrc
->cx
= ws
; szSrc
->cy
= hs
;
262 szDst
->cx
= wd
; szDst
->cy
= hd
;
268 /***********************************************************************
269 * _DIBDRV_InternalAlphaBlend
271 BOOL
_DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
272 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
273 BLENDFUNCTION blendfn
)
279 RECT dstClip
, srcClip
;
281 /* converts to device spaces */
282 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
283 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
284 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
285 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
287 /* from tests, it seems that coords out of phys spaces are not allowed */
288 if(xDst
< 0 || yDst
< 0 || xSrc
< 0 || ySrc
< 0 ||
289 xDst
+ widthDst
> physDevDst
->physBitmap
->width
||
290 yDst
+ heightDst
> physDevDst
->physBitmap
->height
||
291 xSrc
+ widthSrc
> physDevSrc
->physBitmap
->width
||
292 ySrc
+ heightSrc
> physDevSrc
->physBitmap
->height
)
294 SetLastError(ERROR_INVALID_PARAMETER
);
298 /* first clip on physical DC sizes */
299 setPoint(&pd
, xDst
, yDst
);
300 setPoint(&ps
, xSrc
, ySrc
);
301 setSize(&szDst
, widthDst
, heightDst
);
302 setSize(&szSrc
, widthSrc
, heightSrc
);
303 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
304 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
305 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
308 xDst
= pd
.x
; yDst
= pd
.y
;
309 xSrc
= ps
.x
; ySrc
= ps
.y
;
310 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
311 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
313 /* then, do blitting for each dest clip area (no clipping on source) */
315 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
317 RECT
*r
= physDevDst
->regionRects
+ iRec
;
318 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
319 setPoint(&pd
, xDst
, yDst
);
320 setPoint(&ps
, xSrc
, ySrc
);
321 setSize(&szDst
, widthDst
, heightDst
);
322 setSize(&szSrc
, widthSrc
, heightSrc
);
323 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
325 if(physDevDst
->physBitmap
->funcs
->AlphaBlend(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
326 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, blendfn
))
332 /***********************************************************************
335 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
336 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
337 BLENDFUNCTION blendfn
)
341 POINT pd
= {xDst
, yDst
};
342 SIZE szDst
= {widthDst
, heightDst
};
344 CheckMapping(__FUNCTION__
, "DEST", physDevDst
);
345 CheckMapping(__FUNCTION__
, "SOURCE",physDevSrc
);
347 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",
348 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
349 xDst
, yDst
, widthDst
, heightDst
,
350 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
351 xSrc
, ySrc
, widthSrc
, heightSrc
));
353 /* if sizes are null or negative, or source positions are negatives, returns false */
354 if(widthSrc
<= 0 || heightSrc
<= 0 ||
355 widthDst
<= 0 || heightDst
<= 0)
358 SetLastError(ERROR_INVALID_PARAMETER
);
362 /* source sould be a 32 bit DIB */
365 FIXME("Null source bitmap -- shouldn't happen\n");
369 else if(!physDevSrc
->hasDIB
)
371 FIXME("DDB source bitmap still not supported\n");
376 if(physDevDst
->hasDIB
)
378 /* DIB section selected in dest DC, use DIB Engine */
379 MAYBE(TRACE("Blending DIB->DIB\n"));
380 res
= _DIBDRV_InternalAlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
381 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
385 /* DDB selected on dest DC -- must double-convert */
386 HBITMAP tmpDIB
, stock
;
388 MAYBE(TRACE("Blending DIB->DDB\n"));
390 /* we should anyways convert dest to physical coordinates here before processing
391 in order to check its consistency -- source coords will be converted/clipped later
392 As we do a conversion to a temporary DIB for destination, we don't care about it */
393 _DIBDRV_Position_ws2ds(physDevDst
, &pd
.x
, &pd
.y
);
394 _DIBDRV_Sizes_ws2ds(physDevDst
, &szDst
.cx
, &szDst
.cy
);
396 /* test shows that negatives origins are not allowed */
397 if(pd
.x
< 0 || pd
.y
< 0)
399 SetLastError(ERROR_INVALID_PARAMETER
);
404 /* converts dest DDB onto a temporary DIB -- just the needed part */
405 /* WARNING -- that one could fail if rectangle on dest id out of range */
406 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
);
409 ERR("Couldn't convert dest DDB to DIB\n");
414 /* selects the temporary DIB into a temporary DC */
415 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
418 ERR("Couldn't create temporary DC\n");
419 DeleteObject(tmpDIB
);
423 stock
= SelectObject(tmpDC
, tmpDIB
);
426 ERR("Couldn't select temporary DIB into temporary DC\n");
428 DeleteObject(tmpDIB
);
433 /* blends source DIB onto temp DIB and re-blits onto dest DC */
434 res
= GdiAlphaBlend(tmpDC
, 0, 0, szDst
.cx
, szDst
.cy
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
436 MAYBE(TRACE("AlphaBlend failed\n"));
438 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
440 /* frees resources */
441 SelectObject(tmpDC
, stock
);
443 DeleteObject(tmpDIB
);
449 /***********************************************************************
450 * _DIBDRV_InternalBitBlt
452 BOOL
_DIBDRV_InternalBitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
453 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
454 INT xSrc
, INT ySrc
, DWORD rop
)
460 RECT dstClip
, srcClip
;
462 /* converts to device spaces */
463 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
464 _DIBDRV_Sizes_ws2ds(physDevDst
, &width
, &height
);
466 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
468 /* first clip on physical DC sizes */
469 setPoint(&pd
, xDst
, yDst
);
470 setPoint(&ps
, xSrc
, ySrc
);
471 setSize(&sz
, width
, height
);
472 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
476 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
477 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
480 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
483 xDst
= pd
.x
; yDst
= pd
.y
;
484 xSrc
= ps
.x
; ySrc
= ps
.y
;
485 width
= sz
.cx
; height
= sz
.cy
;
487 /* then, do blitting for each dest clip area (no clipping on source) */
489 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
491 RECT
*r
= physDevDst
->regionRects
+ iRec
;
492 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
493 setPoint(&pd
, xDst
, yDst
);
494 setPoint(&ps
, xSrc
, ySrc
);
495 setSize(&sz
, width
, height
);
496 if(!BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
))
498 if(!physDevDst
->physBitmap
->funcs
->BitBlt(physDevDst
, pd
.x
, pd
.y
, sz
.cx
, sz
.cy
, physDevSrc
, ps
.x
, ps
.y
, rop
))
504 /***********************************************************************
506 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
507 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
508 INT xSrc
, INT ySrc
, DWORD rop
)
512 int devXSrc
, devWidth
;
513 int devYSrc
, devHeight
, zeroYSrc
;
515 CheckMapping(__FUNCTION__
, "DEST", physDevDst
);
516 CheckMapping(__FUNCTION__
, "SOURCE",physDevSrc
);
517 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",
518 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
519 xDst
, yDst
, width
, height
,
520 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
523 if(physDevDst
->hasDIB
)
525 /* DIB section selected in dest DC, use DIB Engine */
527 if(!physDevSrc
|| physDevSrc
->hasDIB
)
529 /* source is null or has a DIB, no need to convert anyting */
530 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
534 /* source is a DDB, must convert it to DIB */
536 /* we must differentiate from 2 cases :
537 1) source DC is a memory DC
538 2) source DC is a device DC */
539 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
544 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
547 ERR("Couldn't select out DDB from source HDC\n");
552 /* we need device coordinates for ySrc and height, as the conversion
553 functions operates directly on bitmap without the hdc */
555 _DIBDRV_Position_ws2ds(physDevSrc
, &dummy
, &devYSrc
);
557 _DIBDRV_Sizes_ws2ds(physDevSrc
, &dummy
, &devHeight
);
559 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, devYSrc
, devHeight
);
562 ERR("Failed converting source DDB to DIB\n");
563 SelectObject(physDevSrc
->hdc
, ddb
);
567 SelectObject(physDevSrc
->hdc
, dib
);
569 /* we need to convert the '0' starting position on converted bitmap tp the world
570 space of bitmap's hdc */
572 _DIBDRV_Position_ds2ws(physDevSrc
, &dummy
, &zeroYSrc
);
573 res
= _DIBDRV_InternalBitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, zeroYSrc
, rop
);
574 SelectObject(physDevSrc
->hdc
, ddb
);
585 /* we need device coordinates for ySrc and height, as the conversion
586 functions operates directly on bitmap without the hdc */
589 _DIBDRV_Position_ws2ds(physDevSrc
, &devXSrc
, &devYSrc
);
592 _DIBDRV_Sizes_ws2ds(physDevSrc
, &devWidth
, &devHeight
);
594 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, devXSrc
, devYSrc
, devWidth
, devHeight
);
597 ERR("Failed converting source DDB tp DIB for device DC\n");
601 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
604 ERR("Failed creating temporary memory DC\n");
609 stock
= SelectObject(memHdc
, dib
);
612 ERR("Failed selecting converted DIB into temporary memory DC\n");
618 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
620 SelectObject(memHdc
, stock
);
628 else /* dest is a DDB */
630 /* DDB selected on dest DC, use X11 Driver */
631 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
633 /* source is null or has also a DDB, no need to convert anything */
634 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
635 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
639 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
641 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
644 ERR("Couldn't select out DIB from source HDC\n");
649 /* we need device coordinates for ySrc and height, as the conversion
650 functions operates directly on bitmap without the hdc */
652 _DIBDRV_Position_ws2ds(physDevSrc
, &dummy
, &devYSrc
);
654 _DIBDRV_Sizes_ws2ds(physDevSrc
, &dummy
, &devHeight
);
656 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, devYSrc
, devHeight
);
659 ERR("Failed converting source DIB to DDB\n");
660 SelectObject(physDevSrc
->hdc
, dib
);
664 SelectObject(physDevSrc
->hdc
, ddb
);
666 /* we need to convert the '0' starting position on converted bitmap tp the world
667 space of bitmap's hdc */
669 _DIBDRV_Position_ds2ws(physDevSrc
, &dummy
, &zeroYSrc
);
671 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
672 physDevSrc
->X11PhysDev
, xSrc
, zeroYSrc
, rop
);
673 SelectObject(physDevSrc
->hdc
, dib
);
682 /***********************************************************************
683 * _DIBDRV_InternalStretchBlt
685 BOOL
_DIBDRV_InternalStretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
686 INT widthDst
, INT heightDst
, DIBDRVPHYSDEV
*physDevSrc
,
687 INT xSrc
, INT ySrc
, int widthSrc
, int heightSrc
, DWORD rop
)
693 RECT dstClip
, srcClip
;
695 /* converts to device spaces */
696 _DIBDRV_Position_ws2ds(physDevDst
, &xDst
, &yDst
);
697 _DIBDRV_Sizes_ws2ds(physDevDst
, &widthDst
, &heightDst
);
700 _DIBDRV_Position_ws2ds(physDevSrc
, &xSrc
, &ySrc
);
701 _DIBDRV_Sizes_ws2ds(physDevSrc
, &widthSrc
, &heightSrc
);
704 /* first clip on physical DC sizes */
705 setPoint(&pd
, xDst
, yDst
);
706 setPoint(&ps
, xSrc
, ySrc
);
707 setSize(&szDst
, widthDst
, heightDst
);
708 setSize(&szSrc
, widthSrc
, heightSrc
);
709 setRect(&dstClip
, 0, 0, physDevDst
->physBitmap
->width
, physDevDst
->physBitmap
->height
);
712 setRect(&srcClip
, 0, 0, physDevSrc
->physBitmap
->width
, physDevSrc
->physBitmap
->height
);
713 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
716 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
719 xDst
= pd
.x
; yDst
= pd
.y
;
720 xSrc
= ps
.x
; ySrc
= ps
.y
;
721 widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
722 widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
724 /* then, do blitting for each dest clip area (no clipping on source) */
726 for(iRec
= 0; iRec
< physDevDst
->regionRectCount
; iRec
++)
728 RECT
*r
= physDevDst
->regionRects
+ iRec
;
729 setRect(&dstClip
, r
->left
, r
->top
, r
->right
, r
->bottom
);
730 setPoint(&pd
, xDst
, yDst
);
731 setPoint(&ps
, xSrc
, ySrc
);
732 setSize(&szDst
, widthDst
, heightDst
);
733 setSize(&szSrc
, widthSrc
, heightSrc
);
734 if(!StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
))
736 if(physDevDst
->physBitmap
->funcs
->StretchBlt(physDevDst
, pd
.x
, pd
.y
, szDst
.cx
, szDst
.cy
,
737 physDevSrc
, ps
.x
, ps
.y
, szSrc
.cx
, szSrc
.cy
, rop
))
743 /***********************************************************************
746 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
747 INT widthDst
, INT heightDst
,
748 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
749 INT widthSrc
, INT heightSrc
, DWORD rop
)
753 int devXSrc
, devWidthSrc
;
754 int devYSrc
, devHeightSrc
, zeroYSrc
;
756 /* if source and dest sizes match, just call BitBlt(), it's faster */
757 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
758 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
760 CheckMapping(__FUNCTION__
, "DEST", physDevDst
);
761 CheckMapping(__FUNCTION__
, "SOURCE",physDevSrc
);
762 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",
763 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevDst
->physBitmap
) : "",
764 xDst
, yDst
, widthDst
, heightDst
,
765 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(physDevSrc
->physBitmap
) : "",
766 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
768 if(physDevDst
->hasDIB
)
770 /* DIB section selected in dest DC, use DIB Engine */
772 if(!physDevSrc
|| physDevSrc
->hasDIB
)
774 /* source is null or has a DIB, no need to convert anyting */
775 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
779 /* source is a DDB, must convert it to DIB */
781 /* we must differentiate from 2 cases :
782 1) source DC is a memory DC
783 2) source DC is a device DC */
784 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
789 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
792 ERR("Couldn't select out DDB from source HDC\n");
797 /* we need device coordinates for ySrc and height, as the conversion
798 functions operates directly on bitmap without the hdc */
800 _DIBDRV_Position_ws2ds(physDevSrc
, &dummy
, &devYSrc
);
801 devHeightSrc
= heightSrc
;
802 _DIBDRV_Sizes_ws2ds(physDevSrc
, &dummy
, &devHeightSrc
);
804 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, devYSrc
, devHeightSrc
);
807 ERR("Failed converting source DDB to DIB\n");
808 SelectObject(physDevSrc
->hdc
, ddb
);
812 SelectObject(physDevSrc
->hdc
, dib
);
815 /* we need to convert the '0' starting position on converted bitmap tp the world
816 space of bitmap's hdc */
818 _DIBDRV_Position_ds2ws(physDevSrc
, &dummy
, &zeroYSrc
);
820 res
= _DIBDRV_InternalStretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
821 physDevSrc
, xSrc
, zeroYSrc
, widthSrc
, heightSrc
, rop
);
822 SelectObject(physDevSrc
->hdc
, ddb
);
833 /* we need device coordinates for ySrc and height, as the conversion
834 functions operates directly on bitmap without the hdc */
837 _DIBDRV_Position_ws2ds(physDevSrc
, &devXSrc
, &devYSrc
);
838 devWidthSrc
= widthSrc
;
839 devHeightSrc
= heightSrc
;
840 _DIBDRV_Sizes_ws2ds(physDevSrc
, &devWidthSrc
, &devHeightSrc
);
842 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, devXSrc
, devYSrc
, devWidthSrc
, devHeightSrc
);
845 ERR("Failed converting source DDB tp DIB for device DC\n");
849 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
852 ERR("Failed creating temporary memory DC\n");
857 stock
= SelectObject(memHdc
, dib
);
860 ERR("Failed selecting converted DIB into temporary memory DC\n");
866 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
868 SelectObject(memHdc
, stock
);
876 else /* dest is a DDB */
878 /* DDB selected on dest DC, use X11 Driver */
879 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
881 /* source is null or has also a DDB, no need to convert anything */
882 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
883 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
887 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
890 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
893 ERR("Couldn't select out DIB from source HDC\n");
898 /* we need device coordinates for ySrc and height, as the conversion
899 functions operates directly on bitmap without the hdc */
901 _DIBDRV_Position_ws2ds(physDevSrc
, &dummy
, &devYSrc
);
902 devHeightSrc
= heightSrc
;
903 _DIBDRV_Sizes_ws2ds(physDevSrc
, &dummy
, &devHeightSrc
);
905 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, devYSrc
, devHeightSrc
);
908 ERR("Failed converting source DIB to DDB\n");
909 SelectObject(physDevSrc
->hdc
, dib
);
913 if(!SelectObject(physDevSrc
->hdc
, ddb
))
915 ERR("Failed to select converted DDB into source HDC\n");
916 SelectObject(physDevSrc
->hdc
, dib
);
922 /* we need to convert the '0' starting position on converted bitmap tp the world
923 space of bitmap's hdc */
925 _DIBDRV_Position_ds2ws(physDevSrc
, &dummy
, &zeroYSrc
);
926 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
927 physDevSrc
->X11PhysDev
, xSrc
, zeroYSrc
, widthSrc
, heightSrc
, rop
);
928 SelectObject(physDevSrc
->hdc
, dib
);
937 /***********************************************************************
940 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
944 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
948 /* DIB section selected in, use DIB Engine */
949 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
950 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
954 /* DDB selected in, use X11 driver */
955 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);