b4603e085e81cad72faf111525bce6d56fb6586a
[reactos.git] / reactos / subsys / win32k / dib / dib16bpp.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
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 VOID
26 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
27 {
28 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29 PWORD addr = (PWORD)byteaddr + x;
30
31 *addr = (WORD)c;
32 }
33
34 ULONG
35 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
36 {
37 PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
38 PWORD addr = (PWORD)byteaddr + x;
39
40 return (ULONG)(*addr);
41 }
42
43 VOID
44 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
45 {
46 PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
47
48
49 #ifdef _M_IX86
50 /* This is about 10% faster than the generic C code below */
51 LONG Count = x2 - x1;
52
53 __asm__ __volatile__ (
54 " cld\n"
55 " mov %0, %%eax\n"
56 " shl $16, %%eax\n"
57 " andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
58 " or %0, %%eax\n"
59 " mov %2, %%edi\n"
60 " test $0x03, %%edi\n" /* Align to fullword boundary */
61 " jz 0f\n"
62 " stosw\n"
63 " dec %1\n"
64 " jz 1f\n"
65 "0:\n"
66 " mov %1,%%ecx\n" /* Setup count of fullwords to fill */
67 " shr $1,%%ecx\n"
68 " rep stosl\n" /* The actual fill */
69 " test $0x01, %1\n" /* One left to do at the right side? */
70 " jz 1f\n"
71 " stosw\n"
72 "1:\n"
73 : /* no output */
74 : "r"(c), "r"(Count), "m"(addr)
75 : "%eax", "%ecx", "%edi");
76 #else /* _M_IX86 */
77 LONG cx = x1;
78 DWORD cc;
79
80 if (0 != (cx & 0x01)) {
81 *((PWORD) addr) = c;
82 cx++;
83 addr = (PDWORD)((PWORD)(addr) + 1);
84 }
85 cc = ((c & 0xffff) << 16) | (c & 0xffff);
86 while(cx + 1 < x2) {
87 *addr++ = cc;
88 cx += 2;
89 }
90 if (cx < x2) {
91 *((PWORD) addr) = c;
92 }
93 #endif /* _M_IX86 */
94 }
95
96
97 VOID
98 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
99 {
100 #ifdef _M_IX86
101 asm volatile(
102 " testl %2, %2" "\n\t"
103 " jle 2f" "\n\t"
104 " movl %2, %%ecx" "\n\t"
105 " shrl $2, %2" "\n\t"
106 " andl $3, %%ecx" "\n\t"
107 " jz 1f" "\n\t"
108 "0:" "\n\t"
109 " movw %%ax, (%0)" "\n\t"
110 " addl %1, %0" "\n\t"
111 " decl %%ecx" "\n\t"
112 " jnz 0b" "\n\t"
113 " testl %2, %2" "\n\t"
114 " jz 2f" "\n\t"
115 "1:" "\n\t"
116 " movw %%ax, (%0)" "\n\t"
117 " addl %1, %0" "\n\t"
118 " movw %%ax, (%0)" "\n\t"
119 " addl %1, %0" "\n\t"
120 " movw %%ax, (%0)" "\n\t"
121 " addl %1, %0" "\n\t"
122 " movw %%ax, (%0)" "\n\t"
123 " addl %1, %0" "\n\t"
124 " decl %2" "\n\t"
125 " jnz 1b" "\n\t"
126 "2:" "\n\t"
127 : /* no output */
128 : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
129 "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
130 : "cc", "memory", "%ecx");
131 #else
132 PBYTE byteaddr = SurfObj->pvScan0 + y1 * SurfObj->lDelta;
133 PWORD addr = (PWORD)byteaddr + x;
134 LONG lDelta = SurfObj->lDelta;
135
136 byteaddr = (PBYTE)addr;
137 while(y1++ < y2) {
138 *addr = (WORD)c;
139
140 byteaddr += lDelta;
141 addr = (PWORD)byteaddr;
142 }
143 #endif
144 }
145
146 BOOLEAN
147 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
148 {
149 LONG i, j, sx, sy, xColor, f1;
150 PBYTE SourceBits, DestBits, SourceLine, DestLine;
151 PBYTE SourceBits_4BPP, SourceLine_4BPP;
152 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
153
154 switch(BltInfo->SourceSurface->iBitmapFormat)
155 {
156 case BMF_1BPP:
157 sx = BltInfo->SourcePoint.x;
158 sy = BltInfo->SourcePoint.y;
159
160 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
161 {
162 sx = BltInfo->SourcePoint.x;
163 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
164 {
165 if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
166 {
167 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
168 } else {
169 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
170 }
171 sx++;
172 }
173 sy++;
174 }
175 break;
176
177 case BMF_4BPP:
178 SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
179
180 for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
181 {
182 SourceLine_4BPP = SourceBits_4BPP;
183 sx = BltInfo->SourcePoint.x;
184 f1 = sx & 1;
185
186 for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
187 {
188 xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
189 (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
190 DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
191 if(f1 == 1) { SourceLine_4BPP++; f1 = 0; } else { f1 = 1; }
192 sx++;
193 }
194
195 SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
196 }
197 break;
198
199 case BMF_8BPP:
200 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
201 DestLine = DestBits;
202
203 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
204 {
205 SourceBits = SourceLine;
206 DestBits = DestLine;
207
208 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
209 {
210 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
211 SourceBits += 1;
212 DestBits += 2;
213 }
214
215 SourceLine += BltInfo->SourceSurface->lDelta;
216 DestLine += BltInfo->DestSurface->lDelta;
217 }
218 break;
219
220 case BMF_16BPP:
221 if (NULL == BltInfo->XlateSourceToDest || 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
222 {
223 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
224 {
225 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
226 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
227 {
228 RtlMoveMemory(DestBits, SourceBits, 2 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
229 SourceBits += BltInfo->SourceSurface->lDelta;
230 DestBits += BltInfo->DestSurface->lDelta;
231 }
232 }
233 else
234 {
235 SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
236 DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
237 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
238 {
239 RtlMoveMemory(DestBits, SourceBits, 2 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
240 SourceBits -= BltInfo->SourceSurface->lDelta;
241 DestBits -= BltInfo->DestSurface->lDelta;
242 }
243 }
244 }
245 else
246 {
247 if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
248 {
249 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
250 DestLine = DestBits;
251 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
252 {
253 SourceBits = SourceLine;
254 DestBits = DestLine;
255 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
256 {
257 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((WORD *)SourceBits));
258 SourceBits += 2;
259 DestBits += 2;
260 }
261 SourceLine += BltInfo->SourceSurface->lDelta;
262 DestLine += BltInfo->DestSurface->lDelta;
263 }
264 }
265 else
266 {
267 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
268 DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
269 for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
270 {
271 SourceBits = SourceLine;
272 DestBits = DestLine;
273 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
274 {
275 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((WORD *)SourceBits));
276 SourceBits += 2;
277 DestBits += 2;
278 }
279 SourceLine -= BltInfo->SourceSurface->lDelta;
280 DestLine -= BltInfo->DestSurface->lDelta;
281 }
282 }
283 }
284 break;
285
286 case BMF_24BPP:
287 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
288 DestLine = DestBits;
289
290 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
291 {
292 SourceBits = SourceLine;
293 DestBits = DestLine;
294
295 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
296 {
297 xColor = (*(SourceBits + 2) << 0x10) +
298 (*(SourceBits + 1) << 0x08) +
299 (*(SourceBits));
300 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
301 SourceBits += 3;
302 DestBits += 2;
303 }
304
305 SourceLine += BltInfo->SourceSurface->lDelta;
306 DestLine += BltInfo->DestSurface->lDelta;
307 }
308 break;
309
310 case BMF_32BPP:
311 SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
312 DestLine = DestBits;
313
314 for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
315 {
316 SourceBits = SourceLine;
317 DestBits = DestLine;
318
319 for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
320 {
321 *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *((PDWORD) SourceBits));
322 SourceBits += 4;
323 DestBits += 2;
324 }
325
326 SourceLine += BltInfo->SourceSurface->lDelta;
327 DestLine += BltInfo->DestSurface->lDelta;
328 }
329 break;
330
331 default:
332 DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
333 return FALSE;
334 }
335
336 return TRUE;
337 }
338
339 /* Optimize for bitBlt */
340 BOOLEAN
341 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
342 {
343 ULONG DestY;
344
345 #ifdef _M_IX86
346 /* This is about 10% faster than the generic C code below */
347 ULONG delta = DestSurface->lDelta;
348 ULONG width = (DestRect->right - DestRect->left) ;
349 PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
350 color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
351 color += (color<<16);
352
353 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
354 {
355 __asm__ __volatile__ (
356 " cld\n"
357 " mov %1,%%ebx\n"
358 " mov %2,%%edi\n"
359 " test $0x03, %%edi\n" /* Align to fullword boundary */
360 " jz .FL1\n"
361 " stosw\n"
362 " dec %%ebx\n"
363 " jz .FL2\n"
364 ".FL1:\n"
365 " mov %%ebx,%%ecx\n" /* Setup count of fullwords to fill */
366 " shr $1,%%ecx\n"
367 " rep stosl\n" /* The actual fill */
368 " test $0x01, %%ebx\n" /* One left to do at the right side? */
369 " jz .FL2\n"
370 " stosw\n"
371 ".FL2:\n"
372 :
373 : "a" (color), "r" (width), "m" (pos)
374 : "%ecx", "%ebx", "%edi");
375 pos =(PULONG)((ULONG_PTR)pos + delta);
376 }
377
378 #else /* _M_IX86 */
379
380 for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
381 {
382 DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
383 }
384 #endif
385 return TRUE;
386 }
387 /*
388 =======================================
389 Stretching functions goes below
390 Some parts of code are based on an
391 article "Bresenhame image scaling"
392 Dr. Dobb Journal, May 2002
393 =======================================
394 */
395
396 typedef unsigned short PIXEL;
397
398 /* 16-bit HiColor (565 format) */
399 __inline PIXEL average16(PIXEL a, PIXEL b)
400 {
401 // This one doesn't work
402 /*
403 if (a == b) {
404 return a;
405 } else {
406 unsigned short mask = ~ (((a | b) & 0x0410) << 1);
407 return ((a & mask) + (b & mask)) >> 1;
408 }*/ /* if */
409
410 // This one should be correct, but it's too long
411 /*
412 unsigned char r1, g1, b1, r2, g2, b2, rr, gr, br;
413 unsigned short res;
414
415 r1 = (a & 0xF800) >> 11;
416 g1 = (a & 0x7E0) >> 5;
417 b1 = (a & 0x1F);
418
419 r2 = (b & 0xF800) >> 11;
420 g2 = (b & 0x7E0) >> 5;
421 b2 = (b & 0x1F);
422
423 rr = (r1+r2) / 2;
424 gr = (g1+g2) / 2;
425 br = (b1+b2) / 2;
426
427 res = (rr << 11) + (gr << 5) + br;
428
429 return res;
430 */
431 return a; // FIXME: Depend on SetStretchMode
432 }
433
434 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
435 void ScaleLineAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth)
436 {
437 int NumPixels = TgtWidth;
438 int IntPart = SrcWidth / TgtWidth;
439 int FractPart = SrcWidth % TgtWidth;
440 int Mid = TgtWidth >> 1;
441 int E = 0;
442 int skip;
443 PIXEL p;
444
445 skip = (TgtWidth < SrcWidth) ? 0 : (TgtWidth / (2*SrcWidth) + 1);
446 NumPixels -= skip;
447
448 while (NumPixels-- > 0) {
449 p = *Source;
450 if (E >= Mid)
451 p = average16(p, *(Source+1));
452 *Target++ = p;
453 Source += IntPart;
454 E += FractPart;
455 if (E >= TgtWidth) {
456 E -= TgtWidth;
457 Source++;
458 } /* if */
459 } /* while */
460 while (skip-- > 0)
461 *Target++ = *Source;
462 }
463
464 static BOOLEAN
465 FinalCopy16(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex,
466 UINT DestY, RECTL *DestRect)
467 {
468 LONG Left, Right;
469
470 while (ClipSpans[*SpanIndex].Y < DestY
471 || (ClipSpans[*SpanIndex].Y == DestY
472 && ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left))
473 {
474 (*SpanIndex)++;
475 if (ClipSpansCount <= *SpanIndex)
476 {
477 /* No more spans, everything else is clipped away, we're done */
478 return FALSE;
479 }
480 }
481 while (ClipSpans[*SpanIndex].Y == DestY)
482 {
483 if (ClipSpans[*SpanIndex].X < DestRect->right)
484 {
485 Left = max(ClipSpans[*SpanIndex].X, DestRect->left);
486 Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right);
487 memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left,
488 (Right - Left) * sizeof(PIXEL));
489 }
490 (*SpanIndex)++;
491 if (ClipSpansCount <= *SpanIndex)
492 {
493 /* No more spans, everything else is clipped away, we're done */
494 return FALSE;
495 }
496 }
497
498 return TRUE;
499 }
500
501 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
502 BOOLEAN ScaleRectAvg16(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
503 RECTL* DestRect, RECTL *SourceRect,
504 POINTL* MaskOrigin, POINTL BrushOrigin,
505 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
506 ULONG Mode)
507 {
508 int NumPixels = DestRect->bottom - DestRect->top;
509 int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceSurf->lDelta) >> 1;
510 int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top);
511 int Mid = (DestRect->bottom - DestRect->top) >> 1;
512 int E = 0;
513 int skip;
514 PIXEL *ScanLine, *ScanLineAhead;
515 PIXEL *PrevSource = NULL;
516 PIXEL *PrevSourceAhead = NULL;
517 PIXEL *Target = (PIXEL *) ((PBYTE)DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left);
518 PIXEL *Source = (PIXEL *) ((PBYTE)SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left);
519 PSPAN ClipSpans;
520 UINT ClipSpansCount;
521 UINT SpanIndex;
522 LONG DestY;
523
524 if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect))
525 {
526 return FALSE;
527 }
528 if (0 == ClipSpansCount)
529 {
530 /* No clip spans == empty clipping region, everything clipped away */
531 ASSERT(NULL == ClipSpans);
532 return TRUE;
533 }
534 skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1);
535 NumPixels -= skip;
536
537 ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
538 ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL));
539
540 DestY = DestRect->top;
541 SpanIndex = 0;
542 while (NumPixels-- > 0) {
543 if (Source != PrevSource) {
544 if (Source == PrevSourceAhead) {
545 /* the next scan line has already been scaled and stored in
546 * ScanLineAhead; swap the buffers that ScanLine and ScanLineAhead
547 * point to
548 */
549 PIXEL *tmp = ScanLine;
550 ScanLine = ScanLineAhead;
551 ScanLineAhead = tmp;
552 } else {
553 ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
554 } /* if */
555 PrevSource = Source;
556 } /* if */
557
558 if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceSurf->lDelta)) {
559 int x;
560 ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceSurf->lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
561 for (x = 0; x < DestRect->right - DestRect->left; x++)
562 ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]);
563 PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceSurf->lDelta);
564 } /* if */
565
566 if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
567 {
568 /* No more spans, everything else is clipped away, we're done */
569 ExFreePool(ClipSpans);
570 ExFreePool(ScanLine);
571 ExFreePool(ScanLineAhead);
572 return TRUE;
573 }
574 DestY++;
575 Target = (PIXEL *)((BYTE *)Target + DestSurf->lDelta);
576 Source += IntPart;
577 E += FractPart;
578 if (E >= DestRect->bottom - DestRect->top) {
579 E -= DestRect->bottom - DestRect->top;
580 Source = (PIXEL *)((BYTE *)Source + SourceSurf->lDelta);
581 } /* if */
582 } /* while */
583
584 if (skip > 0 && Source != PrevSource)
585 ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left);
586 while (skip-- > 0) {
587 if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect))
588 {
589 /* No more spans, everything else is clipped away, we're done */
590 ExFreePool(ClipSpans);
591 ExFreePool(ScanLine);
592 ExFreePool(ScanLineAhead);
593 return TRUE;
594 }
595 DestY++;
596 Target = (PIXEL *)((BYTE *)Target + DestSurf->lDelta);
597 } /* while */
598
599 ExFreePool(ClipSpans);
600 ExFreePool(ScanLine);
601 ExFreePool(ScanLineAhead);
602
603 return TRUE;
604 }
605
606
607 //NOTE: If you change something here, please do the same in other dibXXbpp.c files!
608 BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
609 RECTL* DestRect, RECTL *SourceRect,
610 POINTL* MaskOrigin, POINTL BrushOrigin,
611 CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation,
612 ULONG Mode)
613 {
614 LONG SrcSizeY;
615 LONG SrcSizeX;
616 LONG DesSizeY;
617 LONG DesSizeX;
618 LONG sx;
619 LONG sy;
620 LONG DesX;
621 LONG DesY;
622 LONG color;
623 PULONG DestBits;
624 LONG DifflDelta;
625
626
627 DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
628 BitsPerFormat(SourceSurf->iBitmapFormat), SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
629 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
630
631 SrcSizeY = SourceRect->bottom - SourceRect->top;
632 SrcSizeX = SourceRect->right - SourceRect->left;
633
634 DesSizeY = DestRect->bottom - DestRect->top;
635 DesSizeX = DestRect->right - DestRect->left;
636
637 switch(SourceSurf->iBitmapFormat)
638 {
639
640 case BMF_1BPP:
641 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
642 /* This is a reference implementation, it hasn't been optimized for speed */
643
644 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
645 DestRect->top * DestSurf->lDelta);
646
647 DifflDelta = DestSurf->lDelta - (DesSizeX << 1);
648
649 for (DesY=0; DesY<DesSizeY; DesY++)
650 {
651 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
652
653 for (DesX=0; DesX<DesSizeX; DesX++)
654 {
655
656 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
657
658 if(DIB_1BPP_GetPixel(SourceSurf, sx, sy) == 0)
659 {
660 *DestBits = XLATEOBJ_iXlate(ColorTranslation, 0);
661 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
662 }
663 else
664 {
665 *DestBits = XLATEOBJ_iXlate(ColorTranslation, 1);
666 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
667 }
668 }
669 DestBits = (PULONG)((ULONG_PTR)DestBits + DifflDelta);
670 }
671 break;
672
673 case BMF_4BPP:
674 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
675 /* This is a reference implementation, it hasn't been optimized for speed */
676
677 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
678 DestRect->top * DestSurf->lDelta);
679
680 DifflDelta = DestSurf->lDelta - (DesSizeX << 1);
681
682 for (DesY=0; DesY<DesSizeY; DesY++)
683 {
684 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
685
686 for (DesX=0; DesX<DesSizeX; DesX++)
687 {
688
689 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
690 color = DIB_4BPP_GetPixel(SourceSurf, sx, sy);
691
692 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
693 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
694 }
695 DestBits = (PULONG)((ULONG_PTR)DestBits + DifflDelta);
696 }
697 break;
698
699 case BMF_8BPP:
700 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
701 /* This is a reference implementation, it hasn't been optimized for speed */
702
703 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
704 DestRect->top * DestSurf->lDelta);
705
706 DifflDelta = DestSurf->lDelta - (DesSizeX << 1);
707
708 for (DesY=0; DesY<DesSizeY; DesY++)
709 {
710 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
711
712 for (DesX=0; DesX<DesSizeX; DesX++)
713 {
714
715 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
716 color = DIB_8BPP_GetPixel(SourceSurf, sx, sy);
717
718 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
719 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
720 }
721 DestBits = (PULONG)((ULONG_PTR)DestBits + DifflDelta);
722 }
723 break;
724
725
726 case BMF_24BPP:
727 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
728 /* This is a reference implementation, it hasn't been optimized for speed */
729
730 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
731 DestRect->top * DestSurf->lDelta);
732
733 DifflDelta = DestSurf->lDelta - (DesSizeX << 1);
734
735 for (DesY=0; DesY<DesSizeY; DesY++)
736 {
737 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
738
739 for (DesX=0; DesX<DesSizeX; DesX++)
740 {
741
742 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
743 color = DIB_24BPP_GetPixel(SourceSurf, sx, sy);
744
745 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
746 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
747 }
748 DestBits = (PULONG)((ULONG_PTR)DestBits + DifflDelta);
749 }
750 break;
751
752 case BMF_32BPP:
753 /* FIXME : MaskOrigin, BrushOrigin, ClipRegion, Mode ? */
754 /* This is a reference implementation, it hasn't been optimized for speed */
755
756 DestBits = (PULONG)((PBYTE)DestSurf->pvScan0 + (DestRect->left << 1) +
757 DestRect->top * DestSurf->lDelta);
758
759 DifflDelta = DestSurf->lDelta - (DesSizeX << 1);
760
761 for (DesY=0; DesY<DesSizeY; DesY++)
762 {
763 sy = ((DesY * SrcSizeY) / DesSizeY) + SourceRect->top;
764
765 for (DesX=0; DesX<DesSizeX; DesX++)
766 {
767
768 sx = ((DesX * SrcSizeX) / DesSizeX) + SourceRect->left;
769 color = DIB_32BPP_GetPixel(SourceSurf, sx, sy);
770
771 *DestBits = XLATEOBJ_iXlate(ColorTranslation, color);
772 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
773 }
774 DestBits = (PULONG)((ULONG_PTR)DestBits + DifflDelta);
775 }
776 break;
777
778 case BMF_16BPP:
779 return ScaleRectAvg16(DestSurf, SourceSurf, DestRect, SourceRect, MaskOrigin, BrushOrigin,
780 ClipRegion, ColorTranslation, Mode);
781 break;
782
783 default:
784 DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", BitsPerFormat(SourceSurf->iBitmapFormat));
785 return FALSE;
786 }
787
788
789
790 return TRUE;
791 }
792
793 BOOLEAN
794 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
795 RECTL* DestRect, POINTL *SourcePoint,
796 XLATEOBJ *ColorTranslation, ULONG iTransColor)
797 {
798 ULONG RoundedRight, X, Y, SourceX, SourceY, Source, wd, Dest;
799 ULONG *DestBits;
800
801 RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
802 SourceY = SourcePoint->y;
803 DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
804 (DestRect->left << 1) +
805 DestRect->top * DestSurf->lDelta);
806 wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
807
808 for(Y = DestRect->top; Y < DestRect->bottom; Y++)
809 {
810 SourceX = SourcePoint->x;
811 for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
812 {
813 Dest = *DestBits;
814
815 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
816 if(Source != iTransColor)
817 {
818 Dest &= 0xFFFF0000;
819 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
820 }
821
822 Source = DIB_GetSourceIndex(SourceSurf, SourceX + 1, SourceY);
823 if(Source != iTransColor)
824 {
825 Dest &= 0xFFFF;
826 Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
827 }
828
829 *DestBits = Dest;
830 }
831
832 if(X < DestRect->right)
833 {
834 Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
835 if(Source != iTransColor)
836 {
837 *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation, Source);
838 }
839
840 DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
841 }
842 SourceY++;
843 DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
844 }
845
846 return TRUE;
847 }
848
849 typedef union {
850 ULONG ul;
851 struct {
852 UCHAR red;
853 UCHAR green;
854 UCHAR blue;
855 UCHAR alpha;
856 } col;
857 } NICEPIXEL32;
858
859 typedef union {
860 USHORT us;
861 struct {
862 USHORT red:5,
863 green:6,
864 blue:5;
865 } col;
866 } NICEPIXEL16;
867
868 STATIC inline UCHAR
869 Clamp5(ULONG val)
870 {
871 return (val > 31) ? 31 : val;
872 }
873
874 STATIC inline UCHAR
875 Clamp6(ULONG val)
876 {
877 return (val > 63) ? 63 : val;
878 }
879
880 BOOLEAN
881 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
882 RECTL* SourceRect, CLIPOBJ* ClipRegion,
883 XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
884 {
885 INT Rows, Cols, SrcX, SrcY;
886 register PUSHORT Dst;
887 ULONG DstDelta;
888 BLENDFUNCTION BlendFunc;
889 register NICEPIXEL16 DstPixel;
890 register NICEPIXEL32 SrcPixel;
891 UCHAR Alpha, SrcBpp;
892
893 DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
894 SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
895 DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
896
897 ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
898 DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
899
900 BlendFunc = BlendObj->BlendFunction;
901 if (BlendFunc.BlendOp != AC_SRC_OVER)
902 {
903 DPRINT1("BlendOp != AC_SRC_OVER\n");
904 return FALSE;
905 }
906 if (BlendFunc.BlendFlags != 0)
907 {
908 DPRINT1("BlendFlags != 0\n");
909 return FALSE;
910 }
911 if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
912 {
913 DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
914 return FALSE;
915 }
916 if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
917 BitsPerFormat(Source->iBitmapFormat) != 32)
918 {
919 DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
920 return FALSE;
921 }
922
923 Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
924 (DestRect->left << 1));
925 DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
926 SrcBpp = BitsPerFormat(Source->iBitmapFormat);
927
928 Rows = DestRect->bottom - DestRect->top;
929 SrcY = SourceRect->top;
930 while (--Rows >= 0)
931 {
932 Cols = DestRect->right - DestRect->left;
933 SrcX = SourceRect->left;
934 while (--Cols >= 0)
935 {
936 if (SrcBpp <= 16)
937 {
938 DstPixel.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
939 SrcPixel.col.red = (DstPixel.col.red << 3) | (DstPixel.col.red >> 2);
940 SrcPixel.col.green = (DstPixel.col.green << 2) | (DstPixel.col.green >> 4);
941 SrcPixel.col.blue = (DstPixel.col.blue << 3) | (DstPixel.col.blue >> 2);
942 }
943 else
944 {
945 SrcPixel.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
946 }
947 SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
948 SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
949 SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
950 SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
951
952 Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
953 SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
954
955 DstPixel.us = *Dst;
956 DstPixel.col.red = Clamp5(DstPixel.col.red * (255 - Alpha) / 255 + (SrcPixel.col.red >> 3));
957 DstPixel.col.green = Clamp6(DstPixel.col.green * (255 - Alpha) / 255 + (SrcPixel.col.green >> 2));
958 DstPixel.col.blue = Clamp5(DstPixel.col.blue * (255 - Alpha) / 255 + (SrcPixel.col.blue >> 3));
959 *Dst++ = DstPixel.us;
960 }
961 Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
962 SrcY++;
963 }
964
965 return TRUE;
966 }
967
968 /* EOF */