2 * PROJECT: Win32 subsystem
3 * LICENSE: See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/dib/dib24bpp.c
5 * PURPOSE: Device Independant Bitmap functions, 24bpp
6 * PROGRAMMERS: Jason Filby
17 DIB_24BPP_PutPixel(SURFOBJ
*SurfObj
, LONG x
, LONG y
, ULONG c
)
19 PBYTE addr
= (PBYTE
)SurfObj
->pvScan0
+ (y
* SurfObj
->lDelta
) + (x
<< 1) + x
;
20 *(PUSHORT
)(addr
) = c
& 0xFFFF;
21 *(addr
+ 2) = (c
>> 16) & 0xFF;
25 DIB_24BPP_GetPixel(SURFOBJ
*SurfObj
, LONG x
, LONG y
)
27 PBYTE addr
= (PBYTE
)SurfObj
->pvScan0
+ y
* SurfObj
->lDelta
+ (x
<< 1) + x
;
28 return *(PUSHORT
)(addr
) + (*(addr
+ 2) << 16);
34 DIB_24BPP_VLine(SURFOBJ
*SurfObj
, LONG x
, LONG y1
, LONG y2
, ULONG c
)
36 PBYTE addr
= (PBYTE
)SurfObj
->pvScan0
+ y1
* SurfObj
->lDelta
+ (x
<< 1) + x
;
37 LONG lDelta
= SurfObj
->lDelta
;
42 *(PUSHORT
)(addr
) = c
& 0xFFFF;
43 *(addr
+ 2) = c
>> 16;
50 DIB_24BPP_BitBltSrcCopy(PBLTINFO BltInfo
)
52 LONG i
, j
, sx
, sy
, xColor
, f1
;
53 PBYTE SourceBits
, DestBits
, SourceLine
, DestLine
;
54 PBYTE SourceBits_4BPP
, SourceLine_4BPP
;
55 PWORD SourceBits_16BPP
, SourceLine_16BPP
;
57 DestBits
= (PBYTE
)BltInfo
->DestSurface
->pvScan0
+ (BltInfo
->DestRect
.top
* BltInfo
->DestSurface
->lDelta
) + BltInfo
->DestRect
.left
* 3;
59 switch(BltInfo
->SourceSurface
->iBitmapFormat
)
62 sx
= BltInfo
->SourcePoint
.x
;
63 sy
= BltInfo
->SourcePoint
.y
;
65 for (j
=BltInfo
->DestRect
.top
; j
<BltInfo
->DestRect
.bottom
; j
++)
67 sx
= BltInfo
->SourcePoint
.x
;
68 for (i
=BltInfo
->DestRect
.left
; i
<BltInfo
->DestRect
.right
; i
++)
70 if(DIB_1BPP_GetPixel(BltInfo
->SourceSurface
, sx
, sy
) == 0)
72 DIB_24BPP_PutPixel(BltInfo
->DestSurface
, i
, j
, XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, 0));
74 DIB_24BPP_PutPixel(BltInfo
->DestSurface
, i
, j
, XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, 1));
83 SourceBits_4BPP
= (PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ (BltInfo
->SourcePoint
.y
* BltInfo
->SourceSurface
->lDelta
) + (BltInfo
->SourcePoint
.x
>> 1);
85 for (j
=BltInfo
->DestRect
.top
; j
<BltInfo
->DestRect
.bottom
; j
++)
87 SourceLine_4BPP
= SourceBits_4BPP
;
89 sx
= BltInfo
->SourcePoint
.x
;
92 for (i
=BltInfo
->DestRect
.left
; i
<BltInfo
->DestRect
.right
; i
++)
94 xColor
= XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
,
95 (*SourceLine_4BPP
& altnotmask
[f1
]) >> (4 * (1 - f1
)));
96 *DestLine
++ = xColor
& 0xff;
97 *(PWORD
)DestLine
= xColor
>> 8;
99 if(f1
== 1) { SourceLine_4BPP
++; f1
= 0; } else { f1
= 1; }
103 SourceBits_4BPP
+= BltInfo
->SourceSurface
->lDelta
;
104 DestBits
+= BltInfo
->DestSurface
->lDelta
;
109 SourceLine
= (PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ (BltInfo
->SourcePoint
.y
* BltInfo
->SourceSurface
->lDelta
) + BltInfo
->SourcePoint
.x
;
112 for (j
= BltInfo
->DestRect
.top
; j
< BltInfo
->DestRect
.bottom
; j
++)
114 SourceBits
= SourceLine
;
117 for (i
= BltInfo
->DestRect
.left
; i
< BltInfo
->DestRect
.right
; i
++)
119 xColor
= XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, *SourceBits
);
120 *DestBits
= xColor
& 0xff;
121 *(PWORD
)(DestBits
+ 1) = xColor
>> 8;
126 SourceLine
+= BltInfo
->SourceSurface
->lDelta
;
127 DestLine
+= BltInfo
->DestSurface
->lDelta
;
132 SourceBits_16BPP
= (PWORD
)((PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ (BltInfo
->SourcePoint
.y
* BltInfo
->SourceSurface
->lDelta
) + 2 * BltInfo
->SourcePoint
.x
);
134 for (j
=BltInfo
->DestRect
.top
; j
<BltInfo
->DestRect
.bottom
; j
++)
136 SourceLine_16BPP
= SourceBits_16BPP
;
139 for (i
=BltInfo
->DestRect
.left
; i
<BltInfo
->DestRect
.right
; i
++)
141 xColor
= XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, *SourceLine_16BPP
);
142 *DestLine
++ = xColor
& 0xff;
143 *(PWORD
)DestLine
= xColor
>> 8;
148 SourceBits_16BPP
= (PWORD
)((PBYTE
)SourceBits_16BPP
+ BltInfo
->SourceSurface
->lDelta
);
149 DestBits
+= BltInfo
->DestSurface
->lDelta
;
154 if (NULL
== BltInfo
->XlateSourceToDest
|| 0 != (BltInfo
->XlateSourceToDest
->flXlate
& XO_TRIVIAL
))
156 if (BltInfo
->DestRect
.top
< BltInfo
->SourcePoint
.y
)
158 SourceBits
= (PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ (BltInfo
->SourcePoint
.y
* BltInfo
->SourceSurface
->lDelta
) + 3 * BltInfo
->SourcePoint
.x
;
159 for (j
= BltInfo
->DestRect
.top
; j
< BltInfo
->DestRect
.bottom
; j
++)
161 RtlMoveMemory(DestBits
, SourceBits
, 3 * (BltInfo
->DestRect
.right
- BltInfo
->DestRect
.left
));
162 SourceBits
+= BltInfo
->SourceSurface
->lDelta
;
163 DestBits
+= BltInfo
->DestSurface
->lDelta
;
168 SourceBits
= (PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ ((BltInfo
->SourcePoint
.y
+ BltInfo
->DestRect
.bottom
- BltInfo
->DestRect
.top
- 1) * BltInfo
->SourceSurface
->lDelta
) + 3 * BltInfo
->SourcePoint
.x
;
169 DestBits
= (PBYTE
)BltInfo
->DestSurface
->pvScan0
+ ((BltInfo
->DestRect
.bottom
- 1) * BltInfo
->DestSurface
->lDelta
) + 3 * BltInfo
->DestRect
.left
;
170 for (j
= BltInfo
->DestRect
.bottom
- 1; BltInfo
->DestRect
.top
<= j
; j
--)
172 RtlMoveMemory(DestBits
, SourceBits
, 3 * (BltInfo
->DestRect
.right
- BltInfo
->DestRect
.left
));
173 SourceBits
-= BltInfo
->SourceSurface
->lDelta
;
174 DestBits
-= BltInfo
->DestSurface
->lDelta
;
180 sx
= BltInfo
->SourcePoint
.x
;
181 sy
= BltInfo
->SourcePoint
.y
;
183 for (j
=BltInfo
->DestRect
.top
; j
<BltInfo
->DestRect
.bottom
; j
++)
185 sx
= BltInfo
->SourcePoint
.x
;
186 for (i
=BltInfo
->DestRect
.left
; i
<BltInfo
->DestRect
.right
; i
++)
188 DWORD pixel
= DIB_24BPP_GetPixel(BltInfo
->SourceSurface
, sx
, sy
);
189 DIB_24BPP_PutPixel(BltInfo
->DestSurface
, i
, j
, XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, pixel
));
198 SourceLine
= (PBYTE
)BltInfo
->SourceSurface
->pvScan0
+ (BltInfo
->SourcePoint
.y
* BltInfo
->SourceSurface
->lDelta
) + 4 * BltInfo
->SourcePoint
.x
;
201 for (j
= BltInfo
->DestRect
.top
; j
< BltInfo
->DestRect
.bottom
; j
++)
203 SourceBits
= SourceLine
;
206 for (i
= BltInfo
->DestRect
.left
; i
< BltInfo
->DestRect
.right
; i
++)
208 xColor
= XLATEOBJ_iXlate(BltInfo
->XlateSourceToDest
, *((PDWORD
) SourceBits
));
209 *DestBits
= xColor
& 0xff;
210 *(PWORD
)(DestBits
+ 1) = xColor
>> 8;
215 SourceLine
+= BltInfo
->SourceSurface
->lDelta
;
216 DestLine
+= BltInfo
->DestSurface
->lDelta
;
221 DbgPrint("DIB_24BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo
->SourceSurface
->iBitmapFormat
));
229 DIB_24BPP_BitBlt(PBLTINFO BltInfo
)
232 ULONG SourceX
, SourceY
;
234 ULONG Dest
, Source
= 0, Pattern
= 0;
239 UsesSource
= ROP4_USES_SOURCE(BltInfo
->Rop4
);
240 UsesPattern
= ROP4_USES_PATTERN(BltInfo
->Rop4
);
242 SourceY
= BltInfo
->SourcePoint
.y
;
244 (PBYTE
)BltInfo
->DestSurface
->pvScan0
+
245 (BltInfo
->DestRect
.left
<< 1) + BltInfo
->DestRect
.left
+
246 BltInfo
->DestRect
.top
* BltInfo
->DestSurface
->lDelta
);
250 if (BltInfo
->PatternSurface
)
252 PatternY
= (BltInfo
->DestRect
.top
- BltInfo
->BrushOrigin
.y
) %
253 BltInfo
->PatternSurface
->sizlBitmap
.cy
;
258 Pattern
= BltInfo
->Brush
->iSolidColor
;
262 for (DestY
= BltInfo
->DestRect
.top
; DestY
< BltInfo
->DestRect
.bottom
; DestY
++)
264 SourceX
= BltInfo
->SourcePoint
.x
;
266 for (DestX
= BltInfo
->DestRect
.left
; DestX
< BltInfo
->DestRect
.right
; DestX
++, DestBits
+= 3, SourceX
++)
268 Dest
= *((PUSHORT
)DestBits
) + (*(DestBits
+ 2) << 16);
272 Source
= DIB_GetSource(BltInfo
->SourceSurface
, SourceX
, SourceY
, BltInfo
->XlateSourceToDest
);
275 if (BltInfo
->PatternSurface
)
277 Pattern
= DIB_GetSourceIndex(BltInfo
->PatternSurface
, (DestX
- BltInfo
->BrushOrigin
.x
) % BltInfo
->PatternSurface
->sizlBitmap
.cx
, PatternY
);
280 Dest
= DIB_DoRop(BltInfo
->Rop4
, Dest
, Source
, Pattern
) & 0xFFFFFF;
281 *(PUSHORT
)(DestBits
) = Dest
& 0xFFFF;
282 *(DestBits
+ 2) = Dest
>> 16;
286 if (BltInfo
->PatternSurface
)
289 PatternY
%= BltInfo
->PatternSurface
->sizlBitmap
.cy
;
291 DestBits
-= (BltInfo
->DestRect
.right
- BltInfo
->DestRect
.left
) * 3;
292 DestBits
+= BltInfo
->DestSurface
->lDelta
;
298 /* BitBlt Optimize */
300 DIB_24BPP_ColorFill(SURFOBJ
* DestSurface
, RECTL
* DestRect
, ULONG color
)
304 #if defined(_M_IX86) && !defined(_MSC_VER)
305 PBYTE xaddr
= (PBYTE
)DestSurface
->pvScan0
+ DestRect
->top
* DestSurface
->lDelta
+ (DestRect
->left
<< 1) + DestRect
->left
;
308 ULONG xCount
=DestRect
->right
- DestRect
->left
;
310 for (DestY
= DestRect
->top
; DestY
< DestRect
->bottom
; DestY
++)
314 xaddr
= (PBYTE
)((ULONG_PTR
)addr
+ DestSurface
->lDelta
);
318 /* For small fills, don't bother doing anything fancy */
321 *(PUSHORT
)(addr
) = color
;
323 *(addr
) = color
>> 16;
329 /* Align to 4-byte address */
330 while (0 != ((ULONG_PTR
) addr
& 0x3))
332 *(PUSHORT
)(addr
) = color
;
334 *(addr
) = color
>> 16;
338 /* If the color we need to fill with is 0ABC, then the final mem pattern
339 * (note little-endianness) would be:
341 * |C.B.A|C.B.A|C.B.A|C.B.A| <- pixel borders
342 * |C.B.A.C|B.A.C.B|A.C.B.A| <- ULONG borders
344 * So, taking endianness into account again, we need to fill with these
345 * ULONGs: CABC BCAB ABCA */
347 /* This is about 30% faster than the generic C code below */
348 __asm__
__volatile__ (
350 " andl $0xffffff, %%ecx\n" /* 0ABC */
351 " movl %%ecx, %%ebx\n" /* Construct BCAB in ebx */
353 " movl %%ecx, %%eax\n"
355 " orl %%eax, %%ebx\n"
356 " movl %%ecx, %%edx\n" /* Construct ABCA in edx */
358 " movl %%ecx, %%eax\n"
360 " orl %%eax, %%edx\n"
361 " movl %%ecx, %%eax\n" /* Construct CABC in eax */
363 " orl %%ecx, %%eax\n"
364 " movl %2, %%ecx\n" /* Load count */
366 " movl %3, %%edi\n" /* Load dest */
368 " movl %%eax, (%%edi)\n" /* Store 4 pixels, 12 bytes */
369 " movl %%ebx, 4(%%edi)\n"
370 " movl %%edx, 8(%%edi)\n"
376 : "m"(color
), "m"(Count
), "m"(addr
)
377 : "%eax", "%ebx", "%ecx", "%edx", "%edi");
378 Count
= Count
& 0x03;
381 *(PUSHORT
)(addr
) = color
;
383 *(addr
) = color
>> 16;
390 for (DestY
= DestRect
->top
; DestY
< DestRect
->bottom
; DestY
++)
392 DIB_24BPP_HLine(DestSurface
, DestRect
->left
, DestRect
->right
, DestY
, color
);
399 DIB_24BPP_TransparentBlt(SURFOBJ
*DestSurf
, SURFOBJ
*SourceSurf
,
400 RECTL
* DestRect
, RECTL
*SourceRect
,
401 XLATEOBJ
*ColorTranslation
, ULONG iTransColor
)
403 ULONG X
, Y
, SourceX
, SourceY
= 0, Source
= 0, wd
, Dest
;
411 DstHeight
= DestRect
->bottom
- DestRect
->top
;
412 DstWidth
= DestRect
->right
- DestRect
->left
;
413 SrcHeight
= SourceRect
->bottom
- SourceRect
->top
;
414 SrcWidth
= SourceRect
->right
- SourceRect
->left
;
416 DestBits
= (BYTE
*)((PBYTE
)DestSurf
->pvScan0
+
417 (DestRect
->left
* 3) +
418 DestRect
->top
* DestSurf
->lDelta
);
419 wd
= DestSurf
->lDelta
- ((DestRect
->right
- DestRect
->left
) * 3);
421 for(Y
= DestRect
->top
; Y
< DestRect
->bottom
; Y
++)
423 SourceY
= SourceRect
->top
+(Y
- DestRect
->top
) * SrcHeight
/ DstHeight
;
424 for(X
= DestRect
->left
; X
< DestRect
->right
; X
++, DestBits
+= 3)
426 SourceX
= SourceRect
->left
+(X
- DestRect
->left
) * SrcWidth
/ DstWidth
;
427 if (SourceX
>= 0 && SourceY
>= 0 &&
428 SourceSurf
->sizlBitmap
.cx
> SourceX
&& SourceSurf
->sizlBitmap
.cy
> SourceY
)
430 Source
= DIB_GetSourceIndex(SourceSurf
, SourceX
, SourceY
);
431 if(Source
!= iTransColor
)
433 Dest
= XLATEOBJ_iXlate(ColorTranslation
, Source
) & 0xFFFFFF;
434 *(PUSHORT
)(DestBits
) = Dest
& 0xFFFF;
435 *(DestBits
+ 2) = Dest
>> 16;
440 DestBits
= (BYTE
*)((ULONG_PTR
)DestBits
+ wd
);
456 static __inline UCHAR
459 return (val
> 255) ? 255 : val
;
463 DIB_24BPP_AlphaBlend(SURFOBJ
* Dest
, SURFOBJ
* Source
, RECTL
* DestRect
,
464 RECTL
* SourceRect
, CLIPOBJ
* ClipRegion
,
465 XLATEOBJ
* ColorTranslation
, BLENDOBJ
* BlendObj
)
467 INT Rows
, Cols
, SrcX
, SrcY
;
469 BLENDFUNCTION BlendFunc
;
470 register NICEPIXEL32 DstPixel
, SrcPixel
;
473 DPRINT("DIB_24BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
474 SourceRect
->left
, SourceRect
->top
, SourceRect
->right
, SourceRect
->bottom
,
475 DestRect
->left
, DestRect
->top
, DestRect
->right
, DestRect
->bottom
);
477 BlendFunc
= BlendObj
->BlendFunction
;
478 if (BlendFunc
.BlendOp
!= AC_SRC_OVER
)
480 DPRINT1("BlendOp != AC_SRC_OVER\n");
483 if (BlendFunc
.BlendFlags
!= 0)
485 DPRINT1("BlendFlags != 0\n");
488 if ((BlendFunc
.AlphaFormat
& ~AC_SRC_ALPHA
) != 0)
490 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc
.AlphaFormat
);
493 if ((BlendFunc
.AlphaFormat
& AC_SRC_ALPHA
) != 0 &&
494 BitsPerFormat(Source
->iBitmapFormat
) != 32)
496 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
500 Dst
= (PUCHAR
)((ULONG_PTR
)Dest
->pvScan0
+ (DestRect
->top
* Dest
->lDelta
) +
501 (DestRect
->left
* 3));
502 SrcBpp
= BitsPerFormat(Source
->iBitmapFormat
);
505 SrcY
= SourceRect
->top
;
506 while (++Rows
<= DestRect
->bottom
- DestRect
->top
)
509 SrcX
= SourceRect
->left
;
510 while (++Cols
<= DestRect
->right
- DestRect
->left
)
512 SrcPixel
.ul
= DIB_GetSource(Source
, SrcX
, SrcY
, ColorTranslation
);
513 SrcPixel
.col
.red
= (SrcPixel
.col
.red
* BlendFunc
.SourceConstantAlpha
) / 255;
514 SrcPixel
.col
.green
= (SrcPixel
.col
.green
* BlendFunc
.SourceConstantAlpha
) / 255;
515 SrcPixel
.col
.blue
= (SrcPixel
.col
.blue
* BlendFunc
.SourceConstantAlpha
) / 255;
516 if (!(BlendFunc
.AlphaFormat
& AC_SRC_ALPHA
))
518 Alpha
= BlendFunc
.SourceConstantAlpha
;
522 Alpha
= (SrcPixel
.col
.alpha
* BlendFunc
.SourceConstantAlpha
) / 255;
525 DstPixel
.col
.red
= Clamp8((*Dst
* (255 - Alpha
)) / 255 + SrcPixel
.col
.red
) ;
526 DstPixel
.col
.green
= Clamp8((*(Dst
+1) * (255 - Alpha
) / 255 + SrcPixel
.col
.green
)) ;
527 DstPixel
.col
.blue
= Clamp8((*(Dst
+2) * (255 - Alpha
)) / 255 + SrcPixel
.col
.blue
) ;
528 *Dst
++ = DstPixel
.col
.red
;
529 *Dst
++ = DstPixel
.col
.green
;
530 *Dst
++ = DstPixel
.col
.blue
;
531 SrcX
= SourceRect
->left
+ (Cols
*(SourceRect
->right
- SourceRect
->left
))/(DestRect
->right
- DestRect
->left
);
533 Dst
= (PUCHAR
)((ULONG_PTR
)Dest
->pvScan0
+ ((DestRect
->top
+ Rows
) * Dest
->lDelta
) +
535 SrcY
= SourceRect
->top
+ (Rows
*(SourceRect
->bottom
- SourceRect
->top
))/(DestRect
->bottom
- DestRect
->top
);