xref: /reactos/win32ss/gdi/dib/dib16bpp.c (revision 4f0b8d3d)
1 /*
2  * PROJECT:         Win32 subsystem
3  * LICENSE:         See COPYING in the top level directory
4  * FILE:            subsystems/win32/win32k/dib/dib16bpp.c
5  * PURPOSE:         Device Independant Bitmap functions, 16bpp
6  * PROGRAMMERS:     Jason Filby
7  *                  Thomas Bluemel
8  *                  Gregor Anich
9  */
10 
11 #include <win32k.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 VOID
17 DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
20   PWORD addr = (PWORD)byteaddr + x;
21 
22   *addr = (WORD)c;
23 }
24 
25 ULONG
26 DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29   PWORD addr = (PWORD)byteaddr + x;
30   return (ULONG)(*addr);
31 }
32 
33 VOID
34 DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
35 {
36   PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
37 
38 #if defined(_M_IX86) && !defined(_MSC_VER)
39   /* This is about 10% faster than the generic C code below */
40   LONG Count = x2 - x1;
41 
42   __asm__ __volatile__ (
43     "  cld\n"
44     "  mov  %0, %%eax\n"
45     "  shl  $16, %%eax\n"
46     "  andl $0xffff, %0\n"  /* If the pixel value is "abcd", put "abcdabcd" in %eax */
47     "  or   %0, %%eax\n"
48     "  mov  %2, %%edi\n"
49     "  test $0x03, %%edi\n" /* Align to fullword boundary */
50     "  jz   0f\n"
51     "  stosw\n"
52     "  dec  %1\n"
53     "  jz   1f\n"
54     "0:\n"
55     "  mov  %1,%%ecx\n"     /* Setup count of fullwords to fill */
56     "  shr  $1,%%ecx\n"
57     "  rep stosl\n"         /* The actual fill */
58     "  test $0x01, %1\n"    /* One left to do at the right side? */
59     "  jz   1f\n"
60     "  stosw\n"
61     "1:\n"
62     : /* no output */
63   : "r"(c), "r"(Count), "m"(addr)
64     : "%eax", "%ecx", "%edi");
65 #else /* _M_IX86 */
66   LONG cx = x1;
67   DWORD cc;
68 
69   if (0 != (cx & 0x01))
70   {
71     *((PWORD) addr) = (WORD)c;
72     cx++;
73     addr = (PDWORD)((PWORD)(addr) + 1);
74   }
75   cc = ((c & 0xffff) << 16) | (c & 0xffff);
76   while(cx + 1 < x2)
77   {
78     *addr++ = cc;
79     cx += 2;
80   }
81   if (cx < x2)
82   {
83     *((PWORD) addr) = (WORD)c;
84   }
85 #endif /* _M_IX86 */
86 }
87 
88 
89 VOID
90 DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
91 {
92 #if defined(_M_IX86) && !defined(_MSC_VER)
93   asm volatile(
94     "   testl %2, %2"       "\n\t"
95     "   jle   2f"           "\n\t"
96     "   movl  %2, %%ecx"    "\n\t"
97     "   shrl  $2, %2"       "\n\t"
98     "   andl  $3, %%ecx"    "\n\t"
99     "   jz    1f"           "\n\t"
100     "0:"                    "\n\t"
101     "   movw  %%ax, (%0)"   "\n\t"
102     "   addl  %1, %0"       "\n\t"
103     "   decl  %%ecx"        "\n\t"
104     "   jnz   0b"           "\n\t"
105     "   testl %2, %2"       "\n\t"
106     "   jz    2f"           "\n\t"
107     "1:"                    "\n\t"
108     "   movw  %%ax, (%0)"   "\n\t"
109     "   addl  %1, %0"       "\n\t"
110     "   movw  %%ax, (%0)"   "\n\t"
111     "   addl  %1, %0"       "\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     "   decl  %2"           "\n\t"
117     "   jnz   1b"           "\n\t"
118     "2:"                    "\n\t"
119     : /* no output */
120   : "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
121     "r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
122     : "cc", "memory", "%ecx");
123 #else
124   PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
125   PWORD addr = (PWORD)byteaddr + x;
126   LONG lDelta = SurfObj->lDelta;
127 
128   byteaddr = (PBYTE)addr;
129   while(y1++ < y2)
130   {
131     *addr = (WORD)c;
132 
133     byteaddr += lDelta;
134     addr = (PWORD)byteaddr;
135   }
136 #endif
137 }
138 
139 BOOLEAN
140 DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
141 {
142   LONG     i, j, sx, sy, xColor, f1;
143   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
144   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
145   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
146 
147   switch(BltInfo->SourceSurface->iBitmapFormat)
148   {
149   case BMF_1BPP:
150     sx = BltInfo->SourcePoint.x;
151     sy = BltInfo->SourcePoint.y;
152     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
153     {
154       sx = BltInfo->SourcePoint.x;
155       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
156       {
157         if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
158         {
159           DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
160             XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
161         }
162         else
163         {
164           DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
165             XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
166         }
167         sx++;
168       }
169       sy++;
170     }
171     break;
172 
173   case BMF_4BPP:
174     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
175       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
176       (BltInfo->SourcePoint.x >> 1);
177 
178     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
179     {
180       SourceLine_4BPP = SourceBits_4BPP;
181       sx = BltInfo->SourcePoint.x;
182       f1 = sx & 1;
183 
184       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
185       {
186         xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
187           (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
188         DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
189         if(f1 == 1)
190         {
191           SourceLine_4BPP++;
192           f1 = 0;
193         }
194         else
195         {
196           f1 = 1;
197         }
198         sx++;
199       }
200       SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
201     }
202     break;
203 
204   case BMF_8BPP:
205     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
206       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
207       BltInfo->SourcePoint.x;
208     DestLine = DestBits;
209 
210     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
211     {
212       SourceBits = SourceLine;
213       DestBits = DestLine;
214 
215       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
216       {
217         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
218           BltInfo->XlateSourceToDest, *SourceBits);
219         SourceBits += 1;
220         DestBits += 2;
221       }
222 
223       SourceLine += BltInfo->SourceSurface->lDelta;
224       DestLine += BltInfo->DestSurface->lDelta;
225     }
226     break;
227 
228   case BMF_16BPP:
229     if (NULL == BltInfo->XlateSourceToDest || 0 !=
230       (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
231     {
232       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
233       {
234         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
235           (BltInfo->SourcePoint.y *
236           BltInfo->SourceSurface->lDelta) + 2 *
237           BltInfo->SourcePoint.x;
238 
239         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
240         {
241           RtlMoveMemory(DestBits, SourceBits,
242             2 * (BltInfo->DestRect.right -
243             BltInfo->DestRect.left));
244 
245           SourceBits += BltInfo->SourceSurface->lDelta;
246           DestBits += BltInfo->DestSurface->lDelta;
247         }
248       }
249       else
250       {
251         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
252           ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
253           BltInfo->DestRect.top - 1) *
254           BltInfo->SourceSurface->lDelta) + 2 *
255           BltInfo->SourcePoint.x;
256 
257         DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
258           ((BltInfo->DestRect.bottom - 1) *
259           BltInfo->DestSurface->lDelta) + 2 *
260           BltInfo->DestRect.left;
261 
262         for (j = BltInfo->DestRect.bottom - 1;
263           BltInfo->DestRect.top <= j; j--)
264         {
265           RtlMoveMemory(DestBits, SourceBits, 2 *
266             (BltInfo->DestRect.right -
267             BltInfo->DestRect.left));
268 
269           SourceBits -= BltInfo->SourceSurface->lDelta;
270           DestBits -= BltInfo->DestSurface->lDelta;
271         }
272       }
273     }
274     else
275     {
276       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
277       {
278         SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
279           (BltInfo->SourcePoint.y *
280           BltInfo->SourceSurface->lDelta) + 2 *
281           BltInfo->SourcePoint.x;
282 
283         DestLine = DestBits;
284         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
285         {
286           SourceBits = SourceLine;
287           DestBits = DestLine;
288           for (i = BltInfo->DestRect.left; i <
289             BltInfo->DestRect.right; i++)
290           {
291             *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
292               BltInfo->XlateSourceToDest,
293               *((WORD *)SourceBits));
294             SourceBits += 2;
295             DestBits += 2;
296           }
297           SourceLine += BltInfo->SourceSurface->lDelta;
298           DestLine += BltInfo->DestSurface->lDelta;
299         }
300       }
301       else
302       {
303         SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
304           ((BltInfo->SourcePoint.y +
305           BltInfo->DestRect.bottom -
306           BltInfo->DestRect.top - 1) *
307           BltInfo->SourceSurface->lDelta) + 2 *
308           BltInfo->SourcePoint.x;
309 
310         DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
311           ((BltInfo->DestRect.bottom - 1) *
312           BltInfo->DestSurface->lDelta) + 2 *
313           BltInfo->DestRect.left;
314 
315         for (j = BltInfo->DestRect.bottom - 1;
316           BltInfo->DestRect.top <= j; j--)
317         {
318           SourceBits = SourceLine;
319           DestBits = DestLine;
320           for (i = BltInfo->DestRect.left; i <
321             BltInfo->DestRect.right; i++)
322           {
323             *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
324               BltInfo->XlateSourceToDest,
325               *((WORD *)SourceBits));
326             SourceBits += 2;
327             DestBits += 2;
328           }
329           SourceLine -= BltInfo->SourceSurface->lDelta;
330           DestLine -= BltInfo->DestSurface->lDelta;
331         }
332       }
333     }
334     break;
335 
336   case BMF_24BPP:
337     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
338       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
339       3 * BltInfo->SourcePoint.x;
340 
341     DestLine = DestBits;
342 
343     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
344     {
345       SourceBits = SourceLine;
346       DestBits = DestLine;
347 
348       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
349       {
350         xColor = (*(SourceBits + 2) << 0x10) +
351           (*(SourceBits + 1) << 0x08) + (*(SourceBits));
352 
353         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
354           BltInfo->XlateSourceToDest, xColor);
355 
356         SourceBits += 3;
357         DestBits += 2;
358       }
359       SourceLine += BltInfo->SourceSurface->lDelta;
360       DestLine += BltInfo->DestSurface->lDelta;
361     }
362     break;
363 
364   case BMF_32BPP:
365     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
366       (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
367       4 * BltInfo->SourcePoint.x;
368 
369     DestLine = DestBits;
370 
371     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
372     {
373       SourceBits = SourceLine;
374       DestBits = DestLine;
375 
376       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
377       {
378         *((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
379           BltInfo->XlateSourceToDest,
380           *((PDWORD) SourceBits));
381         SourceBits += 4;
382         DestBits += 2;
383       }
384 
385       SourceLine += BltInfo->SourceSurface->lDelta;
386       DestLine += BltInfo->DestSurface->lDelta;
387     }
388     break;
389 
390   default:
391     DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
392       BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
393     return FALSE;
394   }
395 
396   return TRUE;
397 }
398 
399 /* Optimize for bitBlt */
400 BOOLEAN
401 DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
402 {
403   LONG DestY;
404 
405 #if defined(_M_IX86) && !defined(_MSC_VER)
406   /* This is about 10% faster than the generic C code below */
407   ULONG delta = DestSurface->lDelta;
408   ULONG width = (DestRect->right - DestRect->left) ;
409   PULONG pos =  (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
410   color = (color&0xffff);  /* If the color value is "abcd", put "abcdabcd" into color */
411   color += (color<<16);
412 
413   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
414   {
415     __asm__ __volatile__ (
416       "cld\n\t"
417       "mov  %1,%%ebx\n\t"
418       "mov  %2,%%edi\n\t"
419       "test $0x03, %%edi\n\t"   /* Align to fullword boundary */
420       "jz   1f\n\t"
421       "stosw\n\t"
422       "dec  %%ebx\n\t"
423       "jz   2f\n"
424       "1:\n\t"
425       "mov  %%ebx,%%ecx\n\t"    /* Setup count of fullwords to fill */
426       "shr  $1,%%ecx\n\t"
427       "rep stosl\n\t"           /* The actual fill */
428       "test $0x01, %%ebx\n\t"   /* One left to do at the right side? */
429       "jz   2f\n\t"
430       "stosw\n"
431       "2:"
432       :
433       : "a" (color), "r" (width), "m" (pos)
434       : "%ecx", "%ebx", "%edi");
435     pos =(PULONG)((ULONG_PTR)pos + delta);
436   }
437 #else /* _M_IX86 */
438 
439   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
440   {
441     DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
442   }
443 #endif
444   return TRUE;
445 }
446 
447 BOOLEAN
448 DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
449                          RECTL*  DestRect,  RECTL *SourceRect,
450                          XLATEOBJ *ColorTranslation, ULONG iTransColor)
451 {
452   LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, wd;
453   ULONG *DestBits, Source, Dest;
454 
455   LONG DstHeight;
456   LONG DstWidth;
457   LONG SrcHeight;
458   LONG SrcWidth;
459 
460   DstHeight = DestRect->bottom - DestRect->top;
461   DstWidth = DestRect->right - DestRect->left;
462   SrcHeight = SourceRect->bottom - SourceRect->top;
463   SrcWidth = SourceRect->right - SourceRect->left;
464 
465   RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
466   DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
467     (DestRect->left << 1) +
468     DestRect->top * DestSurf->lDelta);
469   wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
470 
471   for(Y = DestRect->top; Y < DestRect->bottom; Y++)
472   {
473     SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
474     for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
475     {
476       Dest = *DestBits;
477 
478       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
479       if (SourceX >= 0 && SourceY >= 0 &&
480         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
481       {
482         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
483         if(Source != iTransColor)
484         {
485           Dest &= 0xFFFF0000;
486           Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
487         }
488       }
489 
490       SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
491       if (SourceX >= 0 && SourceY >= 0 &&
492         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
493       {
494         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
495         if(Source != iTransColor)
496         {
497           Dest &= 0xFFFF;
498           Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
499         }
500       }
501 
502       *DestBits = Dest;
503     }
504 
505     if(X < DestRect->right)
506     {
507       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
508       if (SourceX >= 0 && SourceY >= 0 &&
509         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
510       {
511         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
512         if(Source != iTransColor)
513         {
514           *((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
515             Source);
516         }
517       }
518 
519       DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
520     }
521 
522     DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
523   }
524 
525   return TRUE;
526 }
527 
528 /* EOF */
529