20cdcaa6cdd49abd91bee189cfe72da5d138e659
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
));
154 if(physDevDst
->hasDIB
&& physDevSrc
->hasDIB
)
156 /* DIB section selected in both source and dest DC, use DIB Engine */
157 ONCE(FIXME("STUB\n"));
160 else if(!physDevDst
->hasDIB
&& !physDevSrc
->hasDIB
)
162 /* DDB selected in noth source and dest DC, use X11 driver */
163 res
= _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
164 physDevSrc
->X11PhysDev
, xSrc
, ySrc
, widthSrc
, heightSrc
,
167 else if(physDevSrc
->hasDIB
)
169 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
170 ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
171 res
= _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
172 physDevSrc
->X11PhysDev
, xSrc
, ySrc
, widthSrc
, heightSrc
,
175 else /* if(physDevDst->hasDIB) */
177 /* DDB on source, DIB on dest -- must convert source DDB to DIB and use the engine for blit */
178 ONCE(FIXME("STUB\n"));
184 /***********************************************************************
187 BOOL
DIBDRV_BitBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
188 INT width
, INT height
, DIBDRVPHYSDEV
*physDevSrc
,
189 INT xSrc
, INT ySrc
, DWORD rop
)
194 POINT pd
= {xDst
, yDst
};
195 POINT ps
= {xSrc
, ySrc
};
196 SIZE sz
= {width
, height
};
198 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",
199 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
200 xDst
, yDst
, width
, height
,
201 physDevSrc
, physDevSrc
? (physDevSrc
->hasDIB
? "DIB-" : "DDB"): "---", physDevSrc
&& physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
204 if(physDevDst
->hasDIB
)
206 /* DIB section selected in dest DC, use DIB Engine */
209 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
211 if(!physDevSrc
|| physDevSrc
->hasDIB
)
216 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
217 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, &dstClip
);
220 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
223 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
225 /* source is null or has a DIB, no need to convert anyting */
226 res
= physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, xDst
, yDst
, width
, height
, physDevSrc
, xSrc
, ySrc
, rop
);
230 /* source is a DDB, must convert it to DIB */
232 /* don't clip on source */
233 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, 0, &dstClip
);
236 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
238 /* we must differentiate from 2 cases :
239 1) source DC is a memory DC
240 2) source DC is a device DC */
241 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
246 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
249 ERR("Couldn't select out DDB from source HDC\n");
253 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, height
);
256 ERR("Failed converting source DDB to DIB\n");
257 SelectObject(physDevSrc
->hdc
, ddb
);
261 SelectObject(physDevSrc
->hdc
, dib
);
262 res
= physDevDst
->physBitmap
.funcs
->BitBlt(physDevDst
, xDst
, yDst
, width
, height
,
263 physDevSrc
, xSrc
, 0, rop
);
264 SelectObject(physDevSrc
->hdc
, ddb
);
275 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, width
, height
);
278 ERR("Failed converting source DDB tp DIB for device DC\n");
282 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
285 ERR("Failed creating temporary memory DC\n");
290 stock
= SelectObject(memHdc
, dib
);
293 ERR("Failed selecting converted DIB into temporary memory DC\n");
299 res
= BitBlt(physDevDst
->hdc
, xDst
, yDst
, width
, height
, memHdc
, 0, 0, rop
);
301 SelectObject(memHdc
, stock
);
309 else /* dest is a DDB */
311 /* DDB selected on dest DC, use X11 Driver */
312 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
314 /* source is null or has also a DDB, no need to convert anything */
315 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
316 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, rop
);
320 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
326 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
327 res
= BitBlt_ClipAreas(&ps
, &pd
, &sz
, &srcClip
, 0);
333 xDst
= pd
.x
; yDst
= pd
.y
; width
= sz
.cx
; height
= sz
.cy
; xSrc
= ps
.x
; ySrc
= ps
.y
;
335 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
338 ERR("Couldn't select out DIB from source HDC\n");
342 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, height
);
345 ERR("Failed converting source DIB to DDB\n");
346 SelectObject(physDevSrc
->hdc
, dib
);
350 SelectObject(physDevSrc
->hdc
, ddb
);
351 res
= _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, width
, height
,
352 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, rop
);
353 SelectObject(physDevSrc
->hdc
, dib
);
362 /***********************************************************************
365 BOOL
DIBDRV_StretchBlt( DIBDRVPHYSDEV
*physDevDst
, INT xDst
, INT yDst
,
366 INT widthDst
, INT heightDst
,
367 DIBDRVPHYSDEV
*physDevSrc
, INT xSrc
, INT ySrc
,
368 INT widthSrc
, INT heightSrc
, DWORD rop
)
373 POINT pd
= {xDst
, yDst
};
374 POINT ps
= {xSrc
, ySrc
};
375 SIZE szDst
= {widthDst
, heightDst
};
376 SIZE szSrc
= {widthSrc
, heightSrc
};
378 /* if source and dest sizes match, just call BitBlt(), it's faster */
379 if(!physDevSrc
|| (widthDst
== widthSrc
&& heightDst
== heightSrc
))
380 return DIBDRV_BitBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, rop
);
382 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",
383 physDevDst
, physDevDst
->hasDIB
? "DIB-" : "DDB", physDevDst
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevDst
->physBitmap
) : "",
384 xDst
, yDst
, widthDst
, heightDst
,
385 physDevSrc
, physDevSrc
->hasDIB
? "DIB-" : "DDB", physDevSrc
->hasDIB
? _DIBDRVBITMAP_GetFormatName(&physDevSrc
->physBitmap
) : "",
386 xSrc
, ySrc
, widthSrc
, heightSrc
, rop
));
388 if(physDevDst
->hasDIB
)
390 /* DIB section selected in dest DC, use DIB Engine */
393 RECT dstClip
= {0, 0, physDevDst
->physBitmap
.width
, physDevDst
->physBitmap
.height
};
395 if(!physDevSrc
|| physDevSrc
->hasDIB
)
400 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
401 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, &dstClip
);
404 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
407 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
408 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
410 /* source is null or has a DIB, no need to convert anyting */
411 res
= physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
, physDevSrc
, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
415 /* source is a DDB, must convert it to DIB */
417 /* don't clip on source */
418 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, 0, &dstClip
);
421 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
422 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
424 /* we must differentiate from 2 cases :
425 1) source DC is a memory DC
426 2) source DC is a device DC */
427 if(GetObjectType(physDevSrc
->hdc
) == OBJ_MEMDC
)
432 ddb
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
435 ERR("Couldn't select out DDB from source HDC\n");
439 dib
= _DIBDRV_ConvertDDBtoDIB(physDevSrc
->hdc
, ddb
, ySrc
, heightSrc
);
442 ERR("Failed converting source DDB to DIB\n");
443 SelectObject(physDevSrc
->hdc
, ddb
);
447 SelectObject(physDevSrc
->hdc
, dib
);
448 res
= physDevDst
->physBitmap
.funcs
->StretchBlt(physDevDst
, xDst
, yDst
, widthDst
, heightDst
,
449 physDevSrc
, xSrc
, 0, widthSrc
, heightSrc
, rop
);
450 SelectObject(physDevSrc
->hdc
, ddb
);
461 dib
= _DIBDRV_ConvertDevDDBtoDIB(physDevSrc
->hdc
, physDevDst
->hdc
, xSrc
, ySrc
, widthSrc
, heightSrc
);
464 ERR("Failed converting source DDB tp DIB for device DC\n");
468 memHdc
= CreateCompatibleDC(physDevDst
->hdc
);
471 ERR("Failed creating temporary memory DC\n");
476 stock
= SelectObject(memHdc
, dib
);
479 ERR("Failed selecting converted DIB into temporary memory DC\n");
485 res
= StretchBlt(physDevDst
->hdc
, xDst
, yDst
, widthDst
, heightDst
, memHdc
, 0, 0, widthSrc
, widthDst
, rop
);
487 SelectObject(memHdc
, stock
);
495 else /* dest is a DDB */
497 /* DDB selected on dest DC, use X11 Driver */
498 if(!physDevSrc
|| !physDevSrc
->hasDIB
)
500 /* source is null or has also a DDB, no need to convert anything */
501 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
502 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, ySrc
, widthSrc
, heightSrc
, rop
);
506 /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
512 RECT srcClip
= {0, 0, physDevSrc
->physBitmap
.width
, physDevSrc
->physBitmap
.height
};
513 res
= StretchBlt_ClipAreas(&ps
, &pd
, &szSrc
, &szDst
, &srcClip
, 0);
519 xDst
= pd
.x
; yDst
= pd
.y
; widthDst
= szDst
.cx
; heightDst
= szDst
.cy
;
520 xSrc
= ps
.x
; ySrc
= ps
.y
; widthSrc
= szSrc
.cx
; heightSrc
= szSrc
.cy
;
522 dib
= SelectObject(physDevSrc
->hdc
, GetStockObject(DEFAULT_BITMAP
));
525 ERR("Couldn't select out DIB from source HDC\n");
529 ddb
= _DIBDRV_ConvertDIBtoDDB(physDevSrc
->hdc
, dib
, ySrc
, heightSrc
);
532 ERR("Failed converting source DIB to DDB\n");
533 SelectObject(physDevSrc
->hdc
, dib
);
537 if(!SelectObject(physDevSrc
->hdc
, ddb
))
539 ERR("Failed to select converted DDB into source HDC\n");
540 SelectObject(physDevSrc
->hdc
, dib
);
545 res
= _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst
->X11PhysDev
, xDst
, yDst
, widthDst
, heightDst
,
546 physDevSrc
? physDevSrc
->X11PhysDev
: 0, xSrc
, 0, widthSrc
, heightSrc
, rop
);
547 SelectObject(physDevSrc
->hdc
, dib
);
556 /***********************************************************************
559 BOOL
DIBDRV_PatBlt( DIBDRVPHYSDEV
*physDev
, INT left
, INT top
, INT width
, INT height
, DWORD rop
)
563 MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev
, left
, top
, width
, height
, rop
));
567 /* DIB section selected in, use DIB Engine */
568 ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
569 res
= DIBDRV_BitBlt(physDev
, left
, top
, width
, height
, NULL
, 0, 0, rop
);
573 /* DDB selected in, use X11 driver */
574 res
= _DIBDRV_GetDisplayDriver()->pPatBlt(physDev
->X11PhysDev
, left
, top
, width
, height
, rop
);