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