c0227a0384633e0859e2412848dcb23475baa1f6
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 /* clips a source and destination areas to their respective clip rectangles
37 returning both source and dest modified; result is TRUE if clipping
38 leads to a non null rectangle, FALSE otherwise */
39 static BOOL
BitBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*sz
, RECT
*srcClip
, RECT
*dstClip
)
41 int xs1
, ys1
, xs2
, ys2
;
42 int xsc1
, ysc1
, xsc2
, ysc2
;
43 int xd1
, yd1
, xd2
, yd2
;
44 int xdc1
, ydc1
, xdc2
, ydc2
;
48 w
= sz
->cx
; h
= sz
->cy
;
50 /* if sizes null or negative, just return false */
54 /* extract dest area data */
60 /* extract source data */
66 /* if source clip area is not null, do first clipping on it */
69 /* extract source clipping area */
72 xsc2
= srcClip
->right
;
73 ysc2
= srcClip
->bottom
;
75 /* order clip area rectangle points */
76 if(xsc1
> xsc2
) intSwap(&xsc1
, &xsc2
);
77 if(ysc1
> ysc2
) intSwap(&ysc1
, &ysc2
);
79 /* clip on source clipping start point */
80 if(xs1
< xsc1
) { dx
= xsc1
- xs1
; w
-= dx
; xd1
+= dx
; xs1
= xsc1
; }
81 if(ys1
< ysc1
) { dy
= ysc1
- ys1
; h
-= dy
; yd1
+= dy
; ys1
= ysc1
; }
83 /* clip on source clipping end point */
84 if(xs2
> xsc2
) { dx
= xs2
- xsc2
; w
-= dx
; xd2
-= dx
; xs2
= xsc2
; }
85 if(ys2
> ysc2
) { dy
= ys2
- ysc2
; h
-= dy
; yd2
-= dy
; ys2
= ysc2
; }
87 /* if already zero area, return false */
91 /* now do clipping on destination area */
95 /* extract destination clipping area */
98 xdc2
= dstClip
->right
;
99 ydc2
= dstClip
->bottom
;
101 /* order clip area rectangle points */
102 if(xdc1
> xdc2
) intSwap(&xdc1
, &xdc2
);
103 if(ydc1
> ydc2
) intSwap(&ydc1
, &ydc2
);
105 /* clip on dest clipping start point */
106 if(xd1
< xdc1
) { dx
= xdc1
- xd1
; w
-= dx
; xs1
+= dx
; xd1
= xdc1
; }
107 if(yd1
< ydc1
) { dy
= ydc1
- yd1
; h
-= dy
; ys1
+= dy
; yd1
= ydc1
; }
109 /* clip on dest clipping end point */
110 if(xd2
> xdc2
) { dx
= xd2
- xdc2
; w
-= dx
; xs2
-= dx
; xd2
= xdc2
; }
111 if(yd2
> ydc2
) { dy
= yd2
- ydc2
; h
-= dy
; ys2
-= dy
; yd2
= ydc2
; }
113 /* if already zero area, return false */
118 /* sets clipped/translated points and sizes and returns TRUE */
119 ps
->x
= xs1
; ps
->y
= ys1
;
120 pd
->x
= xd1
; pd
->y
= yd1
;
121 sz
->cx
= w
; sz
->cy
= h
;
128 /* clips a source and destination areas to their respective clip rectangles
129 returning both source and dest modified; result is TRUE if clipping
130 leads to a non null rectangle, FALSE otherwise */
131 static BOOL
StretchBlt_ClipAreas(POINT
*ps
, POINT
*pd
, SIZE
*szSrc
, SIZE
*szDst
, RECT
*srcClip
, RECT
*dstClip
)
133 ONCE(FIXME("TO DO\n"));
139 /***********************************************************************
142 BOOL
DIBDRV_AlphaBlend( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
, INT widthDst
, INT heightDst
,
143 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
, INT widthSrc
, INT heightSrc
,
144 BLENDFUNCTION blendfn
)
148 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",
149 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
150 xDst
, yDst
, widthDst
, heightDst
,
151 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
152 xSrc
, ySrc
, widthSrc
, heightSrc
));
155 /* if sizes are null or negative, returns false */
156 if(widthSrc
<= 0 || heightSrc
<= 0 || widthDst
<= 0 || heightDst
<= 0)
162 /* source sould be a 32 bit DIB */
165 FIXME("Null source bitmap -- shouldn't happen\n");
169 else if(!physDevSrc
->hasDIB
)
171 FIXME("DDB source bitmap -- shouldn't happen\n");
176 if(physDevDst
->hasDIB
)
178 /* DIB section selected in dest DC, use DIB Engine */
179 MAYBE(TRACE("Blending DIB->DIB\n"));
180 res
= physDevDst
->physBitmap
.funcs
->AlphaBlend(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
181 physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
185 /* DDB selected on dest DC -- must double-convert */
186 HBITMAP tmpDIB
, stock
;
188 MAYBE(TRACE("Blending DIB->DDB\n"));
190 /* converts dest DDB onto a temporary DIB -- just the needed part */
191 tmpDIB
= _DIBDRV_ConvertDevDDBtoDIB(physDevDst
->hdc
, physDevSrc
->hdc
, xDst
, yDst
, widthDst
, heightDst
);
194 ERR("Couldn't convert dest DDB to DIB\n");
199 /* selects the temporary DIB into a temporary DC */
200 tmpDC
= CreateCompatibleDC(physDevDst
->hdc
);
203 ERR("Couldn't create temporary DC\n");
204 DeleteObject(tmpDIB
);
208 stock
= SelectObject(tmpDC
, tmpDIB
);
211 ERR("Couldn't select temporary DIB into temporary DC\n");
213 DeleteObject(tmpDIB
);
218 /* blends source DIB onto temp DIB and re-blits onto dest DC */
219 res
= GdiAlphaBlend(tmpDC
, 0, 0, widthDst
, heightDst
, physDevSrc
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
, blendfn
);
221 MAYBE(TRACE("AlphaBlend failed\n"));
223 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, tmpDC
, 0, 0, SRCCOPY
);
225 /* frees resources */
226 SelectObject(tmpDC
, stock
);
228 DeleteObject(tmpDIB
);
234 /***********************************************************************
237 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
238 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
239 INT xSrc
, INT ySrc
, DWORD rop
)
244 POINT pd
= {xDst
, yDst
};
245 POINT ps
= {xSrc
, ySrc
};
246 SIZE sz
= {width
, height
};
248 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",
249 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
250 xDst
, yDst
, width
, height
,
251 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
254 if(physDevDst
->hasDIB
)
256 /* DIB section selected in dest DC, use DIB Engine */
259 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
261 if(!physDevSrc
|| physDevSrc
->hasDIB
)
266 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
267 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
270 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
273 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
275 /* source is null or has a DIB, no need to convert anyting */
276 res
= physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
280 /* source is a DDB, must convert it to DIB */
282 /* don't clip on source */
283 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
286 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
288 /* we must differentiate from 2 cases :
289 1) source DC is a memory DC
290 2) source DC is a device DC */
291 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
296 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
299 ERR("Couldn't select out DDB from source HDC\n");
303 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
306 ERR("Failed converting source DDB to DIB\n");
307 SelectObject(physDevSrc
->hdc
, ddb
);
311 SelectObject(physDevSrc
->hdc
, dib
);
312 res
= physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, xDst
, yDst
, width
, height
,
313 physDevSrc
, xSrc
, 0, rop
);
314 SelectObject(physDevSrc
->hdc
, ddb
);
325 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
328 ERR("Failed converting source DDB tp DIB for device DC\n");
332 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
335 ERR("Failed creating temporary memory DC\n");
340 stock
= SelectObject(memHdc
, dib
);
343 ERR("Failed selecting converted DIB into temporary memory DC\n");
349 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
351 SelectObject(memHdc
, stock
);
359 else /* dest is a DDB */
361 /* DDB selected on dest DC, use X11 Driver */
362 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
364 /* source is null or has also a DDB, no need to convert anything */
365 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
366 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
370 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
376 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
377 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
383 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
385 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
388 ERR("Couldn't select out DIB from source HDC\n");
392 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
395 ERR("Failed converting source DIB to DDB\n");
396 SelectObject(physDevSrc
->hdc
, dib
);
400 SelectObject(physDevSrc
->hdc
, ddb
);
401 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
402 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
403 SelectObject(physDevSrc
->hdc
, dib
);
412 /***********************************************************************
415 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
416 INT widthDst
, INT heightDst
,
417 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
418 INT widthSrc
, INT heightSrc
, DWORD rop
)
423 POINT pd
= {xDst
, yDst
};
424 POINT ps
= {xSrc
, ySrc
};
425 SIZE szDst
= {widthDst
, heightDst
};
426 SIZE szSrc
= {widthSrc
, heightSrc
};
428 /* if source and dest sizes match, just call BitBlt(), it's faster */
429 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
430 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
432 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",
433 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
434 xDst
, yDst
, widthDst
, heightDst
,
435 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
436 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
438 if(physDevDst
->hasDIB
)
440 /* DIB section selected in dest DC, use DIB Engine */
443 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
445 if(!physDevSrc
|| physDevSrc
->hasDIB
)
450 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
451 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
454 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
457 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
458 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
460 /* source is null or has a DIB, no need to convert anyting */
461 res
= physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
465 /* source is a DDB, must convert it to DIB */
467 /* don't clip on source */
468 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
471 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
472 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
474 /* we must differentiate from 2 cases :
475 1) source DC is a memory DC
476 2) source DC is a device DC */
477 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
482 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
485 ERR("Couldn't select out DDB from source HDC\n");
489 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
492 ERR("Failed converting source DDB to DIB\n");
493 SelectObject(physDevSrc
->hdc
, ddb
);
497 SelectObject(physDevSrc
->hdc
, dib
);
498 res
= physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
499 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
500 SelectObject(physDevSrc
->hdc
, ddb
);
511 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
514 ERR("Failed converting source DDB tp DIB for device DC\n");
518 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
521 ERR("Failed creating temporary memory DC\n");
526 stock
= SelectObject(memHdc
, dib
);
529 ERR("Failed selecting converted DIB into temporary memory DC\n");
535 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
537 SelectObject(memHdc
, stock
);
545 else /* dest is a DDB */
547 /* DDB selected on dest DC, use X11 Driver */
548 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
550 /* source is null or has also a DDB, no need to convert anything */
551 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
552 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
556 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
562 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
563 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
569 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
570 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
572 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
575 ERR("Couldn't select out DIB from source HDC\n");
579 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
582 ERR("Failed converting source DIB to DDB\n");
583 SelectObject(physDevSrc
->hdc
, dib
);
587 if(!SelectObject(physDevSrc
->hdc
, ddb
))
589 ERR("Failed to select converted DDB into source HDC\n");
590 SelectObject(physDevSrc
->hdc
, dib
);
595 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
596 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
597 SelectObject(physDevSrc
->hdc
, dib
);
606 /***********************************************************************
609 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
613 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
617 /* DIB section selected in, use DIB Engine */
618 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
619 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
623 /* DDB selected in, use X11 driver */
624 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);