Merge from amd64-branch:
[reactos.git] / reactos / subsystems / win32 / win32k / dib / dib1bpp.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$ */
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 VOID
26 DIB_1BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
27 {
28 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
29
30 if (0 == (c & 0x01))
31 *addr &= ~MASK1BPP(x);
32 else
33 *addr |= MASK1BPP(x);
34 }
35
36 ULONG
37 DIB_1BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
38 {
39 PBYTE addr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + (x >> 3);
40
41 return (*addr & MASK1BPP(x) ? 1 : 0);
42 }
43
44 VOID
45 DIB_1BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
46 {
47 while(x1 < x2) {
48 DIB_1BPP_PutPixel(SurfObj, x1, y, c);
49 x1++;
50 }
51 }
52
53 VOID
54 DIB_1BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
55 {
56 while(y1 < y2) {
57 DIB_1BPP_PutPixel(SurfObj, x, y1, c);
58 y1++;
59 }
60 }
61
62 static
63 void
64 DIB_1BPP_BitBltSrcCopy_From1BPP (
65 SURFOBJ* DestSurf,
66 SURFOBJ* SourceSurf,
67 XLATEOBJ* pxlo,
68 PRECTL DestRect,
69 POINTL *SourcePoint )
70 {
71 // the 'window' in this sense is the x-position that corresponds
72 // to the left-edge of the 8-pixel byte we are currently working with.
73 // dwx is current x-window, dwx2 is the 'last' window we need to process
74 int dwx, dwx2; // destination window x-position
75 int swx; // source window y-position
76
77 // left and right edges of source and dest rectangles
78 int dl = DestRect->left; // dest left
79 int dr = DestRect->right-1; // dest right (inclusive)
80 int sl = SourcePoint->x; // source left
81 int sr = sl + dr - dl; // source right (inclusive)
82
83 // which direction are we going?
84 int xinc;
85 int yinc;
86 int ySrcDelta, yDstDelta;
87
88 // following 4 variables are used for the y-sweep
89 int dy; // dest y
90 int dy1; // dest y start
91 int dy2; // dest y end
92 int sy1; // src y start
93
94 int dx;
95 int shift;
96 BYTE srcmask, dstmask, xormask;
97
98 // 'd' and 's' are the dest & src buffer pointers that I use on my x-sweep
99 // 'pd' and 'ps' are the dest & src buffer pointers used on the inner y-sweep
100 PBYTE d, pd; // dest ptrs
101 PBYTE s, ps; // src ptrs
102
103 shift = (dl-sl)&7;
104
105 xormask = 0xFF * XLATEOBJ_iXlate(pxlo, 0);
106
107 if ( DestRect->top <= SourcePoint->y )
108 {
109 // moving up ( scan top -> bottom )
110 dy1 = DestRect->top;
111 dy2 = DestRect->bottom - 1;
112 sy1 = SourcePoint->y;
113 yinc = 1;
114 ySrcDelta = SourceSurf->lDelta;
115 yDstDelta = DestSurf->lDelta;
116 }
117 else
118 {
119 // moving down ( scan bottom -> top )
120 dy1 = DestRect->bottom - 1;
121 dy2 = DestRect->top;
122 sy1 = SourcePoint->y + dy1 - dy2;
123 yinc = -1;
124 ySrcDelta = -SourceSurf->lDelta;
125 yDstDelta = -DestSurf->lDelta;
126 }
127 if ( DestRect->left <= SourcePoint->x )
128 {
129 // moving left ( scan left->right )
130 dwx = dl&~7;
131 swx = (sl-(dl&7))&~7;
132 dwx2 = dr&~7;
133 xinc = 1;
134 }
135 else
136 {
137 // moving right ( scan right->left )
138 dwx = dr&~7;
139 swx = (sr-(dr&7))&~7; //(sr-7)&~7; // we need the left edge of this block... thus the -7
140 dwx2 = dl&~7;
141 xinc = -1;
142 }
143 d = &(((PBYTE)DestSurf->pvScan0)[dy1*DestSurf->lDelta + (dwx>>3)]);
144 s = &(((PBYTE)SourceSurf->pvScan0)[sy1*SourceSurf->lDelta + (swx>>3)]);
145 for ( ;; )
146 {
147 dy = dy1;
148 pd = d;
149 ps = s;
150 srcmask = 0xff;
151 dx = dwx; /* dest x for this pass */
152 if ( dwx < dl )
153 {
154 int diff = dl-dwx;
155 srcmask &= (1<<(8-diff))-1;
156 dx = dl;
157 }
158 if ( dwx+7 > dr )
159 {
160 int diff = dr-dwx+1;
161 srcmask &= ~((1<<(8-diff))-1);
162 }
163 dstmask = ~srcmask;
164
165 // we unfortunately *must* have 5 different versions of the inner
166 // loop to be certain we don't try to read from memory that is not
167 // needed and may in fact be invalid
168 if ( !shift )
169 {
170 for ( ;; )
171 {
172 *pd = (BYTE)((*pd & dstmask) | ((ps[0]^xormask) & srcmask));
173
174 // this *must* be here, because we could be going up *or* down...
175 if ( dy == dy2 )
176 break;
177 dy += yinc;
178 pd += yDstDelta;
179 ps += ySrcDelta;
180 }
181 }
182 else if ( !(0xFF00 & (srcmask<<shift) ) ) // check if ps[0] not needed...
183 {
184 for ( ;; )
185 {
186 *pd = (BYTE)((*pd & dstmask)
187 | ( ( (ps[1]^xormask) >> shift ) & srcmask ));
188
189 // this *must* be here, because we could be going up *or* down...
190 if ( dy == dy2 )
191 break;
192 dy += yinc;
193 pd += yDstDelta;
194 ps += ySrcDelta;
195 }
196 }
197 else if ( !(0xFF & (srcmask<<shift) ) ) // check if ps[1] not needed...
198 {
199 for ( ;; )
200 {
201 *pd = (*pd & dstmask)
202 | ( ( (ps[0]^xormask) << ( 8 - shift ) ) & srcmask );
203
204 // this *must* be here, because we could be going up *or* down...
205 if ( dy == dy2 )
206 break;
207 dy += yinc;
208 pd += yDstDelta;
209 ps += ySrcDelta;
210 }
211 }
212 else // both ps[0] and ps[1] are needed
213 {
214 for ( ;; )
215 {
216 *pd = (*pd & dstmask)
217 | ( ( ( ((ps[1]^xormask))|((ps[0]^xormask)<<8) ) >> shift ) & srcmask );
218
219 // this *must* be here, because we could be going up *or* down...
220 if ( dy == dy2 )
221 break;
222 dy += yinc;
223 pd += yDstDelta;
224 ps += ySrcDelta;
225 }
226 }
227
228 // this *must* be here, because we could be going right *or* left...
229 if ( dwx == dwx2 )
230 break;
231 d += xinc;
232 s += xinc;
233 dwx += xinc<<3;
234 swx += xinc<<3;
235 }
236 }
237
238 BOOLEAN
239 DIB_1BPP_BitBltSrcCopy(PBLTINFO BltInfo)
240 {
241 ULONG Color;
242 LONG i, j, sx, sy = BltInfo->SourcePoint.y;
243
244 switch ( BltInfo->SourceSurface->iBitmapFormat )
245 {
246 case BMF_1BPP:
247 DIB_1BPP_BitBltSrcCopy_From1BPP ( BltInfo->DestSurface, BltInfo->SourceSurface, BltInfo->XlateSourceToDest, &BltInfo->DestRect, &BltInfo->SourcePoint );
248 break;
249
250 case BMF_4BPP:
251 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
252 {
253 sx = BltInfo->SourcePoint.x;
254 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
255 {
256 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_4BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
257 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
258 sx++;
259 }
260 sy++;
261 }
262 break;
263
264 case BMF_8BPP:
265 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
266 {
267 sx = BltInfo->SourcePoint.x;
268 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
269 {
270 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_8BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
271 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
272 sx++;
273 }
274 sy++;
275 }
276 break;
277
278 case BMF_16BPP:
279 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
280 {
281 sx = BltInfo->SourcePoint.x;
282 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
283 {
284 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_16BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
285 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
286 sx++;
287 }
288 sy++;
289 }
290 break;
291
292 case BMF_24BPP:
293 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
294 {
295 sx = BltInfo->SourcePoint.x;
296 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
297 {
298 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_24BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
299 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
300 sx++;
301 }
302 sy++;
303 }
304 break;
305
306 case BMF_32BPP:
307 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
308 {
309 sx = BltInfo->SourcePoint.x;
310 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
311 {
312 Color = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, DIB_32BPP_GetPixel(BltInfo->SourceSurface, sx, sy));
313 DIB_1BPP_PutPixel(BltInfo->DestSurface, i, j, Color);
314 sx++;
315 }
316 sy++;
317 }
318 break;
319
320 default:
321 DbgPrint("DIB_1BPP_BitBlt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
322 return FALSE;
323 }
324
325 return TRUE;
326 }
327
328 BOOLEAN
329 DIB_1BPP_BitBlt(PBLTINFO BltInfo)
330 {
331 ULONG DestX, DestY;
332 ULONG SourceX, SourceY;
333 ULONG PatternY = 0;
334 ULONG Dest, Source = 0, Pattern = 0;
335 ULONG Index;
336 BOOLEAN UsesSource;
337 BOOLEAN UsesPattern;
338 PULONG DestBits;
339 ULONG RoundedRight;
340
341 UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);
342 UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);
343
344 RoundedRight = BltInfo->DestRect.right -
345 ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 31);
346 SourceY = BltInfo->SourcePoint.y;
347
348 if (UsesPattern)
349 {
350 if (BltInfo->PatternSurface)
351 {
352 PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %
353 BltInfo->PatternSurface->sizlBitmap.cy;
354 }
355 else
356 {
357 /* FIXME: Shouldn't it be expanded? */
358 if (BltInfo->Brush)
359 Pattern = BltInfo->Brush->iSolidColor;
360 }
361 }
362
363 for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)
364 {
365 DestX = BltInfo->DestRect.left;
366 SourceX = BltInfo->SourcePoint.x;
367 DestBits = (PULONG)(
368 (PBYTE)BltInfo->DestSurface->pvScan0 +
369 (BltInfo->DestRect.left >> 3) +
370 DestY * BltInfo->DestSurface->lDelta);
371
372 if (DestX & 31)
373 {
374 #if 0
375 /* FIXME: This case is completely untested!!! */
376
377 Dest = *((PBYTE)DestBits);
378 NoBits = 31 - (DestX & 31);
379
380 if (UsesSource)
381 {
382 Source = 0;
383 /* FIXME: This is incorrect! */
384 for (Index = 31 - NoBits; Index >= 0; Index++)
385 Source |= (DIB_GetSource(SourceSurf, SourceX + Index, SourceY, ColorTranslation) << (31 - Index));
386 }
387
388 if (BltInfo->PatternSurface)
389 {
390 Pattern = 0;
391 for (k = 31 - NoBits; k >= 0; k++)
392 Pattern |= (DIB_GetSource(PatternObj, (X + BrushOrigin.x + k) % PatternWidth, PatternY, BltInfo->XlatePatternToDest) << (31 - k));
393 }
394
395 Dest = DIB_DoRop(Rop4, Dest, Source, Pattern);
396 Dest &= ~((1 << (31 - NoBits)) - 1);
397 Dest |= *((PBYTE)DestBits) & ((1 << (31 - NoBits)) - 1);
398
399 *DestBits = Dest;
400
401 DestX += NoBits;
402 SourceX += NoBits;
403 #endif
404 }
405
406 for (; DestX < RoundedRight; DestX += 32, DestBits++, SourceX += 32)
407 {
408 Dest = *DestBits;
409
410 if (UsesSource)
411 {
412 Source = 0;
413 for (Index = 0; Index < 8; Index++)
414 {
415 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index, SourceY, BltInfo->XlateSourceToDest) << (7 - Index);
416 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 8, SourceY, BltInfo->XlateSourceToDest) << (8 + (7 - Index));
417 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 16, SourceY, BltInfo->XlateSourceToDest) << (16 + (7 - Index));
418 Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + Index + 24, SourceY, BltInfo->XlateSourceToDest) << (24 + (7 - Index));
419 }
420 }
421
422 if (BltInfo->PatternSurface)
423 {
424 Pattern = 0;
425 for (Index = 0; Index < 8; Index++)
426 {
427 Pattern |= DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest) << (7 - Index);
428 Pattern |= DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 8) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest) << (8 + (7 - Index));
429 Pattern |= DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 16) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest) << (16 + (7 - Index));
430 Pattern |= DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + Index + 24) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest) << (24 + (7 - Index));
431 }
432 }
433
434 *DestBits = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);
435 }
436
437 if (DestX < BltInfo->DestRect.right)
438 {
439 for (; DestX < BltInfo->DestRect.right; DestX++, SourceX++)
440 {
441 Dest = DIB_1BPP_GetPixel(BltInfo->DestSurface, DestX, DestY);
442
443 if (UsesSource)
444 {
445 Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);
446 }
447
448 if (BltInfo->PatternSurface)
449 {
450 Pattern = DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest);
451 }
452
453 DIB_1BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xF);
454 }
455 }
456
457 SourceY++;
458 if (BltInfo->PatternSurface)
459 {
460 PatternY++;
461 PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;
462 }
463 }
464
465 return TRUE;
466 }
467
468 /* BitBlt Optimize */
469 BOOLEAN
470 DIB_1BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
471 {
472 ULONG DestY;
473
474 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
475 {
476 DIB_1BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
477 }
478
479 return TRUE;
480 }
481
482 BOOLEAN
483 DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
484 RECTL* DestRect, RECTL *SourceRect,
485 XLATEOBJ *ColorTranslation, ULONG iTransColor)
486 {
487 return FALSE;
488 }
489
490 BOOLEAN
491 DIB_1BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
492 RECTL* SourceRect, CLIPOBJ* ClipRegion,
493 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
494 {
495 UNIMPLEMENTED;
496 return FALSE;
497 }
498
499 /* EOF */