xref: /reactos/win32ss/gdi/dib/dib16bpp.c (revision 3476cdae)
1 /*
2  * PROJECT:         Win32 subsystem
3  * LICENSE:         See COPYING in the top level directory
4  * FILE:            win32ss/gdi/dib/dib16bpp.c
5  * PURPOSE:         Device Independant Bitmap functions, 16bpp
6  * PROGRAMMERS:     Jason Filby
7  *                  Thomas Bluemel
8  *                  Gregor Anich
9  *                  Doug Lyons
10  */
11 
12 #include <win32k.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #define DEC_OR_INC(var, decTrue, amount) \
18     ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
19 
20 VOID
21 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
22 {
23   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
24   PWORD addr = (PWORD)byteaddr + x;
25 
26   *addr = (WORD)c;
27 }
28 
29 ULONG
30 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
31 {
32   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
33   PWORD addr = (PWORD)byteaddr + x;
34   return (ULONG)(*addr);
35 }
36 
37 VOID
38 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
39 {
40   PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
41 
42 #if defined(_M_IX86) && !defined(_MSC_VER)
43   /* This is about 10% faster than the generic C code below */
44   LONG Count = x2 - x1;
45 
46   __asm__ __volatile__ (
47     "  cld\n"
48     "  mov  %0, %%eax\n"
49     "  shl  $16, %%eax\n"
50     "  andl $0xffff, %0\n"  /* If the pixel value is "abcd", put "abcdabcd" in %eax */
51     "  or   %0, %%eax\n"
52     "  mov  %2, %%edi\n"
53     "  test $0x03, %%edi\n" /* Align to fullword boundary */
54     "  jz   0f\n"
55     "  stosw\n"
56     "  dec  %1\n"
57     "  jz   1f\n"
58     "0:\n"
59     "  mov  %1,%%ecx\n"     /* Setup count of fullwords to fill */
60     "  shr  $1,%%ecx\n"
61     "  rep stosl\n"         /* The actual fill */
62     "  test $0x01, %1\n"    /* One left to do at the right side? */
63     "  jz   1f\n"
64     "  stosw\n"
65     "1:\n"
66     : /* no output */
67   : "r"(c), "r"(Count), "m"(addr)
68     : "%eax", "%ecx", "%edi");
69 #else /* _M_IX86 */
70   LONG cx = x1;
71   DWORD cc;
72 
73   if (0 != (cx & 0x01))
74   {
75     *((PWORD) addr) = (WORD)c;
76     cx++;
77     addr = (PDWORD)((PWORD)(addr) + 1);
78   }
79   cc = ((c & 0xffff) << 16) | (c & 0xffff);
80   while(cx + 1 < x2)
81   {
82     *addr++ = cc;
83     cx += 2;
84   }
85   if (cx < x2)
86   {
87     *((PWORD) addr) = (WORD)c;
88   }
89 #endif /* _M_IX86 */
90 }
91 
92 
93 VOID
94 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
95 {
96 #if defined(_M_IX86) && !defined(_MSC_VER)
97   asm volatile(
98     "   testl %2, %2"       "\n\t"
99     "   jle   2f"           "\n\t"
100     "   movl  %2, %%ecx"    "\n\t"
101     "   shrl  $2, %2"       "\n\t"
102     "   andl  $3, %%ecx"    "\n\t"
103     "   jz    1f"           "\n\t"
104     "0:"                    "\n\t"
105     "   movw  %%ax, (%0)"   "\n\t"
106     "   addl  %1, %0"       "\n\t"
107     "   decl  %%ecx"        "\n\t"
108     "   jnz   0b"           "\n\t"
109     "   testl %2, %2"       "\n\t"
110     "   jz    2f"           "\n\t"
111     "1:"                    "\n\t"
112     "   movw  %%ax, (%0)"   "\n\t"
113     "   addl  %1, %0"       "\n\t"
114     "   movw  %%ax, (%0)"   "\n\t"
115     "   addl  %1, %0"       "\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     "   decl  %2"           "\n\t"
121     "   jnz   1b"           "\n\t"
122     "2:"                    "\n\t"
123     : /* no output */
124   : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
125     "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
126     : "cc", "memory", "%ecx");
127 #else
128   PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
129   PWORD addr = (PWORD)byteaddr + x;
130   LONG lDelta = SurfObj->lDelta;
131 
132   byteaddr = (PBYTE)addr;
133   while(y1++ < y2)
134   {
135     *addr = (WORD)c;
136 
137     byteaddr += lDelta;
138     addr = (PWORD)byteaddr;
139   }
140 #endif
141 }
142 
143 BOOLEAN
144 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
145 {
146   LONG     i, j, sx, sy, xColor, f1;
147   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
148   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
149   PWORD    Source32, Dest32;
150   DWORD    Index, StartLeft, EndRight;
151   BOOLEAN  bTopToBottom, bLeftToRight;
152 
153   DPRINT("DIB_16BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
154          BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
155          BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
156          BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
157 
158   /* Get back left to right flip here */
159   bLeftToRight = BltInfo->DestRect.left > BltInfo->DestRect.right;
160 
161   /* Check for top to bottom flip needed. */
162   bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
163 
164   DPRINT("BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
165          BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
166 
167   /* Make WellOrdered with top < bottom and left < right */
168   RECTL_vMakeWellOrdered(&BltInfo->DestRect);
169 
170   DPRINT("BPP is '%d/%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
171          BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
172 
173   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
174 
175   switch(BltInfo->SourceSurface->iBitmapFormat)
176   {
177   case BMF_1BPP:
178     DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
179            BltInfo->DestRect.right - BltInfo->DestRect.left);
180     sx = BltInfo->SourcePoint.x;
181 
182     /* This sets sy to the top line */
183     sy = BltInfo->SourcePoint.y;
184 
185     if (bTopToBottom)
186     {
187       /* This sets sy to the bottom line */
188       sy += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
189     }
190 
191     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
192     {
193       sx = BltInfo->SourcePoint.x;
194 
195       if (bLeftToRight)
196       {
197         /* This sets the sx to the rightmost pixel */
198         sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
199         StartLeft = BltInfo->DestRect.left + 1;
200         EndRight = BltInfo->DestRect.right + 1;
201       }
202       else
203       {
204         StartLeft = BltInfo->DestRect.left;
205         EndRight = BltInfo->DestRect.right;
206       }
207 
208       for (i = StartLeft; i < EndRight; i++)
209       {
210         if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
211         {
212           DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
213             XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
214         }
215         else
216         {
217           DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
218             XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
219         }
220         DEC_OR_INC(sx, bLeftToRight, 1);
221       }
222       DEC_OR_INC(sy, bTopToBottom, 1);
223     }
224     break;
225 
226   case BMF_4BPP:
227     DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
228            BltInfo->DestRect.right - BltInfo->DestRect.left);
229 
230     /* This sets SourceBits_4BPP to the top line */
231     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
232       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
233       (BltInfo->SourcePoint.x >> 1);
234 
235     if (bTopToBottom)
236     {
237       /* This sets SourceBits_4BPP to the bottom line */
238       SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
239     }
240 
241     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
242     {
243       SourceLine_4BPP = SourceBits_4BPP;
244       sx = BltInfo->SourcePoint.x;
245       if (bLeftToRight)
246       {
247         /* This sets sx to the rightmost pixel */
248         sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
249       }
250 
251       f1 = sx & 1;
252 
253       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
254       {
255         xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
256           (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
257         DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
258         if(f1 == 1)
259         {
260           DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
261           f1 = 0;
262         }
263         else
264         {
265           f1 = 1;
266         }
267         DEC_OR_INC(sx, bLeftToRight, 1);
268       }
269       DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
270     }
271     break;
272 
273   case BMF_8BPP:
274     DPRINT("8BPP Case Selected with DestRect Width of '%d'.\n",
275            BltInfo->DestRect.right - BltInfo->DestRect.left);
276 
277     /* This sets SourceLine to the top line */
278     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
279       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
280       BltInfo->SourcePoint.x;
281     DestLine = DestBits;
282 
283     if (bTopToBottom)
284     {
285       /* This sets SourceLine to the bottom line */
286       SourceLine += BltInfo->SourceSurface->lDelta
287         * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
288     }
289 
290     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
291     {
292       SourceBits = SourceLine;
293       DestBits = DestLine;
294 
295       if (bLeftToRight)
296       {
297         /* This sets SourceBits to the rightmost pixel */
298         SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
299       }
300 
301       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
302       {
303         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
304           BltInfo->XlateSourceToDest, *SourceBits);
305         DEC_OR_INC(SourceBits, bLeftToRight, 1);
306         DestBits += 2;
307       }
308       DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
309       DestLine += BltInfo->DestSurface->lDelta;
310     }
311     break;
312 
313   case BMF_16BPP:
314     DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
315            BltInfo->DestRect.right - BltInfo->DestRect.left);
316 
317     DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
318            BltInfo->DestRect.left, BltInfo->DestRect.top,
319            BltInfo->DestRect.right, BltInfo->DestRect.bottom,
320            BltInfo->DestRect.right - BltInfo->DestRect.left);
321 
322     if ((BltInfo->XlateSourceToDest == NULL ||
323       (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
324       (!bTopToBottom && !bLeftToRight))
325     {
326       DPRINT("XO_TRIVIAL is TRUE.\n");
327       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
328       {
329         /* This sets SourceBits to the top line */
330         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
331           (BltInfo->SourcePoint.y *
332           BltInfo->SourceSurface->lDelta) + 2 *
333           BltInfo->SourcePoint.x;
334 
335         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
336         {
337           RtlMoveMemory(DestBits, SourceBits,
338             2 * (BltInfo->DestRect.right -
339             BltInfo->DestRect.left));
340 
341           SourceBits += BltInfo->SourceSurface->lDelta;
342           DestBits += BltInfo->DestSurface->lDelta;
343         }
344       }
345       else
346       {
347         /* This sets SourceBits to the bottom line */
348         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
349           ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
350           BltInfo->DestRect.top - 1) *
351           BltInfo->SourceSurface->lDelta) + 2 *
352           BltInfo->SourcePoint.x;
353 
354         DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
355           ((BltInfo->DestRect.bottom - 1) *
356           BltInfo->DestSurface->lDelta) + 2 *
357           BltInfo->DestRect.left;
358 
359         for (j = BltInfo->DestRect.bottom - 1;
360           BltInfo->DestRect.top <= j; j--)
361         {
362           RtlMoveMemory(DestBits, SourceBits, 2 *
363             (BltInfo->DestRect.right -
364             BltInfo->DestRect.left));
365 
366           SourceBits -= BltInfo->SourceSurface->lDelta;
367           DestBits -= BltInfo->DestSurface->lDelta;
368         }
369       }
370     }
371     else
372     {
373       DPRINT("XO_TRIVIAL is NOT TRUE.\n");
374       if (!bTopToBottom && !bLeftToRight)
375       /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
376     {
377       DPRINT("Flip is None.\n");
378       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
379       {
380         SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
381           (BltInfo->SourcePoint.y *
382           BltInfo->SourceSurface->lDelta) + 2 *
383           BltInfo->SourcePoint.x;
384 
385         DestLine = DestBits;
386         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
387         {
388           SourceBits = SourceLine;
389           DestBits = DestLine;
390           for (i = BltInfo->DestRect.left; i <
391             BltInfo->DestRect.right; i++)
392           {
393             *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
394               BltInfo->XlateSourceToDest,
395               *((WORD *)SourceBits));
396             SourceBits += 2;
397             DestBits += 2;
398           }
399           SourceLine += BltInfo->SourceSurface->lDelta;
400           DestLine += BltInfo->DestSurface->lDelta;
401         }
402       }
403       else
404       {
405         SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
406           ((BltInfo->SourcePoint.y +
407           BltInfo->DestRect.bottom -
408           BltInfo->DestRect.top - 1) *
409           BltInfo->SourceSurface->lDelta) + 2 *
410           BltInfo->SourcePoint.x;
411 
412         DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
413           ((BltInfo->DestRect.bottom - 1) *
414           BltInfo->DestSurface->lDelta) + 2 *
415           BltInfo->DestRect.left;
416 
417         for (j = BltInfo->DestRect.bottom - 1;
418           BltInfo->DestRect.top <= j; j--)
419         {
420           SourceBits = SourceLine;
421           DestBits = DestLine;
422           for (i = BltInfo->DestRect.left; i <
423             BltInfo->DestRect.right; i++)
424           {
425             *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
426               BltInfo->XlateSourceToDest,
427               *((WORD *)SourceBits));
428             SourceBits += 2;
429             DestBits += 2;
430           }
431           SourceLine -= BltInfo->SourceSurface->lDelta;
432           DestLine -= BltInfo->DestSurface->lDelta;
433         }
434       }
435     }
436       else
437       {
438         /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
439         BOOL TopToBottomDone = FALSE;
440 
441         if (bLeftToRight)
442         {
443           DPRINT("Flip is bLeftToRight.\n");
444 
445           /* Allocate enough pixels for a row in WORD's */
446           WORD *store = ExAllocatePoolWithTag(NonPagedPool,
447             (BltInfo->DestRect.right - BltInfo->DestRect.left + 1) * 2, TAG_DIB);
448           if (store == NULL)
449           {
450             DPRINT1("Storage Allocation Failed.\n");
451             return FALSE;
452           }
453           WORD  Index;
454 
455           /* This sets SourceBits to the bottom line */
456           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
457             + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
458             * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
459 
460           /* Sets DestBits to the bottom line */
461           DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
462            + (BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta
463            + 2 * BltInfo->DestRect.left + 2;
464 
465           for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
466           {
467             /* Set Dest32 to right pixel */
468             Dest32 = (WORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
469             Source32 = (WORD *) SourceBits;
470 
471             Index = 0;
472 
473             /* Store pixels from left to right */
474             for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
475             {
476               store[Index] = (WORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *(WORD *)Source32++);
477               Index++;
478             }
479 
480             Index = 0;
481 
482             /* Copy stored data to pixels from right to left */
483             for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
484             {
485               *(WORD *)Dest32-- = store[Index];
486               Index++;
487             }
488 
489             SourceBits -= BltInfo->SourceSurface->lDelta;
490             DestBits -= BltInfo->DestSurface->lDelta;
491           }
492           ExFreePoolWithTag(store, TAG_DIB);
493           TopToBottomDone = TRUE;
494         }
495 
496         if (bTopToBottom)
497         {
498           DPRINT("Flip is bTopToBottom.\n");
499 
500           /* Allocate enough pixels for a column in WORD's */
501           WORD *store = ExAllocatePoolWithTag(NonPagedPool,
502             (BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1) * 2, TAG_DIB);
503           if (store == NULL)
504           {
505             DPRINT1("Storage Allocation Failed.\n");
506             return FALSE;
507           }
508 
509           /* This set SourceBits to the top line */
510           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
511             + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
512             + 2 * BltInfo->SourcePoint.x;
513 
514           /* This sets DestBits to the top line */
515           DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
516            + ((BltInfo->DestRect.top) * BltInfo->DestSurface->lDelta)
517            + 2 * BltInfo->DestRect.left;
518 
519           if ((BltInfo->SourceSurface->fjBitmap & BMF_TOPDOWN) == 0)
520           {
521             DestBits += BltInfo->DestSurface->lDelta;
522           }
523 
524           if (bLeftToRight)
525           {
526             DPRINT("Adjusting DestBits for bLeftToRight.\n");
527             DestBits += 2;
528           }
529 
530           /* The TopToBottomDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
531            * and have already completed the bLeftToRight. So we will lose our first flip output
532            * unless we work with its output which is at the destination site. So in this case
533            * our new Source becomes the previous outputs Destination. */
534 
535           if (TopToBottomDone)
536           {
537             /* This sets SourceBits to the top line */
538             SourceBits = DestBits;
539           }
540 
541           for (j = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= j ; j--)
542           {
543             /* Set Dest32 to bottom pixel */
544             Dest32 = (WORD *) DestBits  + (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
545               * BltInfo->DestSurface->lDelta / 2;
546             Source32 = (WORD *) SourceBits;
547 
548             Index = 0;
549 
550             /* Store pixels from top to bottom */
551             for (i = BltInfo->DestRect.top; i <= BltInfo->DestRect.bottom - 1; i++)
552             {
553               store[Index] = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32);
554               Source32 += BltInfo->SourceSurface->lDelta / 2;
555               Index++;
556             }
557 
558             Index = 0;
559 
560             /* Copy stored data to pixels from bottom to top */
561             for (i = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= i; i--)
562             {
563               *Dest32 = store[Index];
564               Dest32 -= BltInfo->DestSurface->lDelta / 2;
565               Index++;
566             }
567             SourceBits += 2;
568             DestBits += 2;
569           }
570           ExFreePoolWithTag(store, TAG_DIB);
571         }
572 
573       }
574     }
575     break;
576 
577   case BMF_24BPP:
578 
579     DPRINT("BMF_24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
580            BltInfo->DestRect.left, BltInfo->DestRect.top,
581            BltInfo->DestRect.right, BltInfo->DestRect.bottom,
582            BltInfo->DestRect.right - BltInfo->DestRect.left);
583 
584     /* This sets SourceLine to the top line */
585     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
586       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
587       3 * BltInfo->SourcePoint.x;
588 
589     if (bTopToBottom)
590     {
591       /* This sets SourceLine to the bottom line */
592       SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
593     }
594     DestLine = DestBits;
595 
596     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
597     {
598       SourceBits = SourceLine;
599       DestBits = DestLine;
600 
601       if (bLeftToRight)
602       {
603         /* This sets the SourceBits to the rightmost pixel */
604         SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
605       }
606       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
607       {
608         xColor = (*(SourceBits + 2) << 0x10) +
609           (*(SourceBits + 1) << 0x08) + (*(SourceBits));
610 
611         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
612           BltInfo->XlateSourceToDest, xColor);
613 
614         DEC_OR_INC(SourceBits, bLeftToRight, 3);
615         DestBits += 2;
616       }
617       DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
618       DestLine += BltInfo->DestSurface->lDelta;
619     }
620     break;
621 
622   case BMF_32BPP:
623     DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
624            BltInfo->DestRect.right - BltInfo->DestRect.left);
625 
626     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
627       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
628       4 * BltInfo->SourcePoint.x;
629 
630     if (bTopToBottom)
631     {
632       /* This sets SourceLine to the bottom line */
633       SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
634     }
635     DestLine = DestBits;
636 
637     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
638     {
639       SourceBits = SourceLine;
640       DestBits = DestLine;
641 
642       if (bLeftToRight)
643       {
644         /* This sets SourceBits to the rightmost pixel */
645         SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
646       }
647 
648       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
649       {
650         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
651           BltInfo->XlateSourceToDest,
652           *((PDWORD) SourceBits));
653         DEC_OR_INC(SourceBits, bLeftToRight, 4);
654         DestBits += 2;
655       }
656 
657       DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
658       DestLine += BltInfo->DestSurface->lDelta;
659     }
660     break;
661 
662   default:
663     DPRINT1("DIB_16BPP_BitBltSrcCopy: Unhandled Source BPP: %u\n",
664             BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
665     return FALSE;
666   }
667 
668   return TRUE;
669 }
670 
671 /* Optimize for bitBlt */
672 BOOLEAN
673 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
674 {
675   LONG DestY;
676 
677   /* Make WellOrdered with top < bottom and left < right */
678   RECTL_vMakeWellOrdered(DestRect);
679 
680 #if defined(_M_IX86) && !defined(_MSC_VER)
681   /* This is about 10% faster than the generic C code below */
682   ULONG delta = DestSurface->lDelta;
683   ULONG width = (DestRect->right - DestRect->left) ;
684   PULONG pos =  (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
685   color = (color&0xffff);  /* If the color value is "abcd", put "abcdabcd" into color */
686   color += (color<<16);
687 
688   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
689   {
690     __asm__ __volatile__ (
691       "cld\n\t"
692       "mov  %1,%%ebx\n\t"
693       "mov  %2,%%edi\n\t"
694       "test $0x03, %%edi\n\t"   /* Align to fullword boundary */
695       "jz   1f\n\t"
696       "stosw\n\t"
697       "dec  %%ebx\n\t"
698       "jz   2f\n"
699       "1:\n\t"
700       "mov  %%ebx,%%ecx\n\t"    /* Setup count of fullwords to fill */
701       "shr  $1,%%ecx\n\t"
702       "rep stosl\n\t"           /* The actual fill */
703       "test $0x01, %%ebx\n\t"   /* One left to do at the right side? */
704       "jz   2f\n\t"
705       "stosw\n"
706       "2:"
707       :
708       : "a" (color), "r" (width), "m" (pos)
709       : "%ecx", "%ebx", "%edi");
710     pos =(PULONG)((ULONG_PTR)pos + delta);
711   }
712 #else /* _M_IX86 */
713 
714   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
715   {
716     DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
717   }
718 #endif
719   return TRUE;
720 }
721 
722 BOOLEAN
723 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
724                          RECTL*  DestRect,  RECTL *SourceRect,
725                          XLATEOBJ *ColorTranslation, ULONG iTransColor)
726 {
727   LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd;
728   ULONG *DestBits, Source, Dest;
729 
730   LONG DstHeight;
731   LONG DstWidth;
732   LONG SrcHeight;
733   LONG SrcWidth;
734 
735   DstHeight = DestRect->bottom - DestRect->top;
736   DstWidth = DestRect->right - DestRect->left;
737   SrcHeight = SourceRect->bottom - SourceRect->top;
738   SrcWidth = SourceRect->right - SourceRect->left;
739 
740   RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
741   DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
742     (DestRect->left << 1) +
743     DestRect->top * DestSurf->lDelta);
744   wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
745 
746   for(Y = DestRect->top; Y < DestRect->bottom; Y++)
747   {
748     SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
749     for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
750     {
751       Dest = *DestBits;
752 
753       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
754       if (SourceX >= 0 && SourceY >= 0 &&
755         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
756       {
757         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
758         if(Source != iTransColor)
759         {
760           Dest &= 0xFFFF0000;
761           Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
762         }
763       }
764 
765       SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
766       if (SourceX >= 0 && SourceY >= 0 &&
767         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
768       {
769         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
770         if(Source != iTransColor)
771         {
772           Dest &= 0xFFFF;
773           Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
774         }
775       }
776 
777       *DestBits = Dest;
778     }
779 
780     if(X < DestRect->right)
781     {
782       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
783       if (SourceX >= 0 && SourceY >= 0 &&
784         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
785       {
786         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
787         if(Source != iTransColor)
788         {
789           *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
790             Source);
791         }
792       }
793 
794       DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
795     }
796 
797     DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
798   }
799 
800   return TRUE;
801 }
802 
803 typedef union
804 {
805   ULONG ul;
806   struct
807   {
808     UCHAR red;
809     UCHAR green;
810     UCHAR blue;
811     UCHAR alpha;
812   } col;
813 } NICEPIXEL32;
814 
815 typedef union
816 {
817   USHORT us;
818   struct
819   {
820     USHORT blue  :5;
821     USHORT green :6;
822     USHORT red   :5;
823   } col;
824 } NICEPIXEL16_565;
825 
826 typedef union
827 {
828   USHORT us;
829   struct
830   {
831     USHORT blue  :5;
832     USHORT green :5;
833     USHORT red   :5;
834     USHORT xxxx  :1;
835   } col;
836 } NICEPIXEL16_555;
837 
838 static __inline UCHAR
839 Clamp6(ULONG val)
840 {
841    return (val > 63) ? 63 : (UCHAR)val;
842 }
843 
844 static __inline UCHAR
845 Clamp5(ULONG val)
846 {
847    return (val > 31) ? 31 : (UCHAR)val;
848 }
849 
850 BOOLEAN
851 DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
852                      RECTL* SourceRect, CLIPOBJ* ClipRegion,
853                      XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
854 {
855   INT DstX, DstY, SrcX, SrcY;
856   BLENDFUNCTION BlendFunc;
857   NICEPIXEL32 SrcPixel32;
858   UCHAR Alpha;
859   EXLATEOBJ* pexlo;
860   EXLATEOBJ exloSrcRGB;
861 
862   DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
863     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
864     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
865 
866   BlendFunc = BlendObj->BlendFunction;
867   if (BlendFunc.BlendOp != AC_SRC_OVER)
868   {
869     DPRINT1("BlendOp != AC_SRC_OVER\n");
870     return FALSE;
871   }
872   if (BlendFunc.BlendFlags != 0)
873   {
874     DPRINT1("BlendFlags != 0\n");
875     return FALSE;
876   }
877   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
878   {
879     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
880     return FALSE;
881   }
882   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
883           (BitsPerFormat(Source->iBitmapFormat) != 32))
884   {
885     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
886     return FALSE;
887   }
888 
889   if (!ColorTranslation)
890   {
891     DPRINT1("ColorTranslation must not be NULL!\n");
892     return FALSE;
893   }
894 
895   pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
896   EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
897 
898   if (pexlo->ppalDst->flFlags & PAL_RGB16_555)
899   {
900       NICEPIXEL16_555 DstPixel16;
901 
902       SrcY = SourceRect->top;
903       DstY = DestRect->top;
904       while ( DstY < DestRect->bottom )
905       {
906         SrcX = SourceRect->left;
907         DstX = DestRect->left;
908         while(DstX < DestRect->right)
909         {
910           SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
911           SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
912           SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
913           SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
914 
915           Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
916                (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
917                BlendFunc.SourceConstantAlpha;
918 
919           Alpha >>= 3;
920 
921           DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF;
922           /* Perform bit loss */
923           SrcPixel32.col.red >>= 3;
924           SrcPixel32.col.green >>= 3;
925           SrcPixel32.col.blue >>= 3;
926 
927           /* Do the blend in the right bit depth */
928           DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha)) / 31 + SrcPixel32.col.red);
929           DstPixel16.col.green = Clamp5((DstPixel16.col.green * (31 - Alpha)) / 31 + SrcPixel32.col.green);
930           DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha)) / 31 + SrcPixel32.col.blue);
931 
932           DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us);
933 
934           DstX++;
935           SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
936                                                 /(DestRect->right-DestRect->left);
937         }
938         DstY++;
939         SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
940                                                 /(DestRect->bottom-DestRect->top);
941       }
942   }
943   else
944   {
945       NICEPIXEL16_565 DstPixel16;
946       UCHAR Alpha6, Alpha5;
947 
948       SrcY = SourceRect->top;
949       DstY = DestRect->top;
950       while ( DstY < DestRect->bottom )
951       {
952         SrcX = SourceRect->left;
953         DstX = DestRect->left;
954         while(DstX < DestRect->right)
955         {
956           SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
957           SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
958           SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
959           SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
960 
961           Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
962                (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
963                BlendFunc.SourceConstantAlpha;
964 
965           Alpha6 = Alpha >> 2;
966           Alpha5 = Alpha >> 3;
967 
968           DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF;
969           /* Perform bit loss */
970           SrcPixel32.col.red >>= 3;
971           SrcPixel32.col.green >>= 2;
972           SrcPixel32.col.blue >>= 3;
973 
974           /* Do the blend in the right bit depth */
975           DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha5)) / 31 + SrcPixel32.col.red);
976           DstPixel16.col.green = Clamp6((DstPixel16.col.green * (63 - Alpha6)) / 63 + SrcPixel32.col.green);
977           DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha5)) / 31 + SrcPixel32.col.blue);
978 
979           DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us);
980 
981           DstX++;
982           SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
983                                                 /(DestRect->right-DestRect->left);
984         }
985         DstY++;
986         SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
987                                                 /(DestRect->bottom-DestRect->top);
988       }
989   }
990 
991   EXLATEOBJ_vCleanup(&exloSrcRGB);
992 
993   return TRUE;
994 }
995 
996 /* EOF */
997