xref: /reactos/sdk/tools/gendib/gendib.c (revision 1734f297)
1 /*
2  * Copyright 2005 Ge van Geldorp (gvg@reactos.com).
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 /*
19  * This is a code generator. It outputs C code which can be compiled using the
20  * standard build tools. It is used to generate code for the DIB Blt routines.
21  * There are a lot of possible Blt routines (256 rop codes, for 6 different
22  * bit depths). It is possible to use a generic Blt routine which handles all
23  * rop codes and all depths. The drawback is that it will be relatively slow.
24  * The other extreme is to write (generate) a separate Blt routine for each
25  * rop code/depth combination. This will result in a extremely large amount
26  * of code. So, we opt for something in between: named rops get their own
27  * routine, unnamed rops are handled by a generic routine.
28  * Basically, what happens is that generic code which looks like:
29  *
30  * for (...)
31  * {
32  *     if (CondA)
33  *     {
34  *         doSomethingA;
35  *     }
36  *     for (...)
37  *     {
38  *         if (CondB)
39  *         {
40  *             doSomethingB;
41  *         }
42  *         else
43  *         {
44  *             doSomethingElseB;
45  *         }
46  *     }
47  * }
48  *
49  * is specialized for named rops to look like:
50  *
51  * if (condC)
52  * {
53  *     if (condD)
54  *     {
55  *         for (...)
56  *         {
57  *             for (...)
58  *             {
59  *                 pumpSomeBytes;
60  *             }
61  *         }
62  *     }
63  *     else
64  *     {
65  *         for (...)
66  *         {
67  *             for (...)
68  *             {
69  *                 pumpSomeBytesSlightlyDifferentE;
70  *             }
71  *         }
72  *     }
73  * }
74  *
75  * i.e. we make the inner loops as tight as possible.
76  * Another optimization is to try to load/store 32 alligned bits at a time from
77  * video memory. Accessing video memory from the CPU is slooooooow, so let's
78  * try to do this as little as possible, even if that means we have to do some
79  * extra operations using main memory.
80  */
81 
82 #include <stdarg.h>
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 
87 #define NDEBUG
88 
89 #define USES_DEST(RopCode)    ((((RopCode) & 0xaa) >> 1) != ((RopCode) & 0x55))
90 #define USES_SOURCE(RopCode)  ((((RopCode) & 0xcc) >> 2) != ((RopCode) & 0x33))
91 #define USES_PATTERN(RopCode) ((((RopCode) & 0xf0) >> 4) != ((RopCode) & 0x0f))
92 
93 #ifdef NDEBUG
94 #define MARK(Out)
95 #else
96 #define MARK(Out) Output((Out), "/* Generated by %s line %d*/\n", \
97                          __FUNCTION__, __LINE__);
98 #endif
99 
100 #define ROPCODE_BLACKNESS   0x00
101 #define ROPCODE_NOTSRCERASE 0x11
102 #define ROPCODE_NOTSRCCOPY  0x33
103 #define ROPCODE_SRCERASE    0x44
104 #define ROPCODE_DSTINVERT   0x55
105 #define ROPCODE_PATINVERT   0x5a
106 #define ROPCODE_SRCINVERT   0x66
107 #define ROPCODE_SRCAND      0x88
108 #define ROPCODE_NOOP        0xaa
109 #define ROPCODE_MERGEPAINT  0xbb
110 #define ROPCODE_MERGECOPY   0xc0
111 #define ROPCODE_SRCCOPY     0xcc
112 #define ROPCODE_SRCPAINT    0xee
113 #define ROPCODE_PATCOPY     0xf0
114 #define ROPCODE_PATPAINT    0xfb
115 #define ROPCODE_WHITENESS   0xff
116 
117 #define ROPCODE_GENERIC     256 /* Special case */
118 
119 typedef struct _ROPINFO
120 {
121     unsigned RopCode;
122     const char *Name;
123     const char *Operation;
124     int UsesDest;
125     int UsesSource;
126     int UsesPattern;
127 }
128 ROPINFO, *PROPINFO;
129 
130 #define FLAG_PATTERNSURFACE      0x01
131 #define FLAG_TRIVIALXLATE        0x02
132 #define FLAG_BOTTOMUP            0x04
133 #define FLAG_FORCENOUSESSOURCE   0x08
134 #define FLAG_FORCERAWSOURCEAVAIL 0x10
135 
136 static PROPINFO
137 FindRopInfo(unsigned RopCode)
138 {
139     static ROPINFO KnownCodes[] =
140     {
141         { ROPCODE_BLACKNESS,   "BLACKNESS",  "0",            0, 0, 0 },
142         { ROPCODE_NOTSRCERASE, "NOTSRCERASE","~(D | S)",     1, 1, 0 },
143         { ROPCODE_NOTSRCCOPY,  "NOTSRCCOPY", "~S",           0, 1, 0 },
144         { ROPCODE_SRCERASE,    "SRCERASE",   "(~D) & S",     1, 1, 0 },
145         { ROPCODE_DSTINVERT,   "DSTINVERT",  "~D",           1, 0, 0 },
146         { ROPCODE_PATINVERT,   "PATINVERT",  "D ^ P",        1, 0, 1 },
147         { ROPCODE_SRCINVERT,   "SRCINVERT",  "D ^ S",        1, 1, 0 },
148         { ROPCODE_SRCAND,      "SRCAND",     "D & S",        1, 1, 0 },
149         { ROPCODE_NOOP,        "NOOP",       "D",            1, 0, 0 },
150         { ROPCODE_MERGEPAINT,  "MERGEPAINT", "D | (~S)",     1, 1, 0 },
151         { ROPCODE_MERGECOPY,   "MERGECOPY",  "S & P",        0, 1, 1 },
152         { ROPCODE_SRCCOPY,     "SRCCOPY",    "S",            0, 1, 0 },
153         { ROPCODE_SRCPAINT,    "SRCPAINT",   "D | S",        1, 1, 0 },
154         { ROPCODE_PATCOPY,     "PATCOPY",    "P",            0, 0, 1 },
155         { ROPCODE_PATPAINT,    "PATPAINT",   "D | (~S) | P", 1, 1, 1 },
156         { ROPCODE_WHITENESS,   "WHITENESS",  "0xffffffff",   0, 0, 0 },
157         { ROPCODE_GENERIC,     NULL,         NULL,           1, 1, 1 }
158     };
159     unsigned Index;
160 
161     for (Index = 0; Index < sizeof(KnownCodes) / sizeof(KnownCodes[0]); Index++)
162     {
163         if (RopCode == KnownCodes[Index].RopCode)
164         {
165             return KnownCodes + Index;
166         }
167     }
168 
169     return NULL;
170 }
171 
172 static void
173 Output(FILE *Out, const char *Fmt, ...)
174 {
175     static unsigned Indent = 0;
176     static int AtBOL = 1;
177     unsigned n;
178     va_list Args;
179 
180     if (strchr(Fmt, '}'))
181     {
182         Indent -= 4;
183     }
184 
185     if (AtBOL)
186     {
187         for (n = 0; n < Indent; n++)
188         {
189             putc(' ', Out);
190         }
191         AtBOL = 0;
192     }
193 
194     va_start(Args, Fmt);
195     vfprintf(Out, Fmt, Args);
196     va_end(Args);
197 
198     if (strchr(Fmt, '{'))
199     {
200         Indent += 4;
201     }
202 
203     AtBOL = '\n' == Fmt[strlen(Fmt) - 1];
204 }
205 
206 static void
207 PrintRoutineName(FILE *Out, unsigned Bpp, PROPINFO RopInfo)
208 {
209     if (NULL != RopInfo && ROPCODE_GENERIC != RopInfo->RopCode)
210     {
211         Output(Out, "DIB_%uBPP_BitBlt_%s", Bpp, RopInfo->Name);
212     }
213     else
214     {
215         Output(Out, "DIB_%uBPP_BitBlt_Generic", Bpp);
216     }
217 }
218 
219 static void
220 CreateShiftTables(FILE *Out)
221 {
222     Output(Out, "\n");
223     Output(Out, "static unsigned Shift1Bpp[] =\n");
224     Output(Out, "{\n");
225     Output(Out, "0,\n");
226     Output(Out, "24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23,\n");
227     Output(Out, "8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7\n");
228     Output(Out, "};\n");
229     Output(Out, "static unsigned Shift4Bpp[] =\n");
230     Output(Out, "{\n");
231     Output(Out, "0,\n");
232     Output(Out, "24, 28, 16, 20, 8, 12, 0, 4\n");
233     Output(Out, "};\n");
234     Output(Out, "static unsigned Shift8Bpp[] =\n");
235     Output(Out, "{\n");
236     Output(Out, "0,\n");
237     Output(Out, "24, 16, 8, 0\n");
238     Output(Out, "};\n");
239     Output(Out, "static unsigned Shift16Bpp[] =\n");
240     Output(Out, "{\n");
241     Output(Out, "0,\n");
242     Output(Out, "16, 0\n");
243     Output(Out, "};\n");
244 }
245 
246 static void
247 CreateOperation(FILE *Out, unsigned Bpp, PROPINFO RopInfo, unsigned SourceBpp,
248                 unsigned Bits)
249 {
250     const char *Cast;
251     const char *Dest;
252     const char *Template;
253 
254     MARK(Out);
255     if (32 == Bits)
256     {
257         Cast = "";
258         Dest = "*DestPtr";
259     }
260     else if (16 == Bpp)
261     {
262         Cast = "(USHORT) ";
263         Dest = "*((PUSHORT) DestPtr)";
264     }
265     else
266     {
267         Cast = "(UCHAR) ";
268         Dest = "*((PUCHAR) DestPtr)";
269     }
270     Output(Out, "%s = ", Dest);
271     if (ROPCODE_GENERIC == RopInfo->RopCode)
272     {
273         Output(Out, "%sDIB_DoRop(BltInfo->Rop4, %s, Source, Pattern)",
274                Cast, Dest);
275     }
276     else
277     {
278         Template = RopInfo->Operation;
279         while ('\0' != *Template)
280         {
281             switch(*Template)
282             {
283             case 'S':
284                 Output(Out, "%sSource", Cast);
285                 break;
286             case 'P':
287                 Output(Out, "%sPattern", Cast);
288                 break;
289             case 'D':
290                 Output(Out, "%s", Dest);
291                 break;
292             default:
293                 Output(Out, "%c", *Template);
294                 break;
295             }
296             Template++;
297         }
298     }
299 }
300 
301 static void
302 CreateBase(FILE *Out, int Source, int Flags, unsigned Bpp)
303 {
304     const char *What = (Source ? "Source" : "Dest");
305 
306     MARK(Out);
307     Output(Out, "%sBase = (char *) BltInfo->%sSurface->pvScan0 +\n", What, What);
308     if (0 == (Flags & FLAG_BOTTOMUP))
309     {
310         if (Source)
311         {
312             Output(Out, "             BltInfo->SourcePoint.y *\n");
313         }
314         else
315         {
316             Output(Out, "           BltInfo->DestRect.top *\n");
317         }
318     }
319     else
320     {
321         if (Source)
322         {
323             Output(Out, "             (BltInfo->SourcePoint.y +\n");
324             Output(Out, "              BltInfo->DestRect.bottom -\n");
325             Output(Out, "              BltInfo->DestRect.top - 1) *\n");
326         }
327         else
328         {
329             Output(Out, "           (BltInfo->DestRect.bottom - 1) *\n");
330         }
331     }
332     Output(Out, "           %sBltInfo->%sSurface->lDelta +\n",
333            Source ? "  " : "", What);
334     if (Source)
335     {
336         Output(Out, "             %sBltInfo->SourcePoint.x",
337                16 < Bpp ? "" : "((");
338     }
339     else
340     {
341         Output(Out, "           BltInfo->DestRect.left");
342     }
343     if (Bpp < 8)
344     {
345         Output(Out, " / %u", 8 / Bpp);
346     }
347     else if (8 < Bpp)
348     {
349         Output(Out, " * %u", Bpp / 8);
350     }
351     if (Source && Bpp <= 16)
352     {
353         Output(Out, ") & ~ 0x3)");
354     }
355     Output(Out, ";\n", Bpp / 8);
356     if (Source && Bpp <= 16)
357     {
358         Output(Out, "BaseSourcePixels = %u - (BltInfo->SourcePoint.x & 0x%x);\n",
359                32 / Bpp, 32 / Bpp - 1);
360     }
361 }
362 
363 static void
364 CreateGetSource(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
365                 unsigned SourceBpp, unsigned Shift)
366 {
367     const char *AssignOp;
368     const char *Before;
369     char After[8];
370 
371     MARK(Out);
372     if (0 == Shift)
373     {
374         AssignOp = "=";
375         Before = "";
376         After[0] = '\0';
377     }
378     else
379     {
380         AssignOp = "|=";
381         Before = "(";
382         sprintf(After, ") << %u", Shift);
383     }
384 
385     if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
386             0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
387     {
388         if (0 == (Flags & FLAG_FORCERAWSOURCEAVAIL) && SourceBpp <= 16)
389         {
390             Output(Out, "if (0 == SourcePixels)\n");
391             Output(Out, "{\n");
392             Output(Out, "RawSource = *SourcePtr++;\n");
393             Output(Out, "SourcePixels = %u;\n", 32 / SourceBpp);
394             Output(Out, "}\n");
395         }
396         Output(Out, "Source %s (%s", AssignOp, Before);
397         if (0 == (Flags & FLAG_TRIVIALXLATE))
398         {
399             Output(Out, "XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, %s",
400                    16 < SourceBpp ? "" : "(");
401         }
402         if (32 == SourceBpp)
403         {
404             Output(Out, "*SourcePtr++");
405         }
406         else if (24 == SourceBpp)
407         {
408             Output(Out, "*(PUSHORT) SourcePtr + (*((PBYTE) SourcePtr + 2) << 16)");
409         }
410         else
411         {
412             Output(Out, "RawSource >> Shift%uBpp[SourcePixels]", SourceBpp);
413         }
414         if (0 == (Flags & FLAG_TRIVIALXLATE))
415         {
416             if (16 < SourceBpp)
417             {
418                 Output(Out, ")");
419             }
420             else
421             {
422                 Output(Out, ") & 0x%x)", (1 << SourceBpp) - 1);
423             }
424         }
425         if (32 == Bpp)
426         {
427             Output(Out, ")%s;\n", After);
428         }
429         else
430         {
431             Output(Out, " & 0x%x)%s;\n", (1 << Bpp) - 1, After);
432         }
433         if (SourceBpp <= 16)
434         {
435             Output(Out, "SourcePixels--;\n");
436         }
437         else if (24 == SourceBpp)
438         {
439             Output(Out, "SourcePtr = (PULONG)((char *) SourcePtr + 3);\n");
440         }
441     }
442 }
443 
444 static void
445 CreateCounts(FILE *Out, unsigned Bpp)
446 {
447     MARK(Out);
448     if (32 != Bpp)
449     {
450         if (8 < Bpp)
451         {
452             Output(Out, "LeftCount = ((ULONG_PTR) DestBase >> 1) & 0x01;\n");
453         }
454         else
455         {
456             Output(Out, "LeftCount = (ULONG_PTR) DestBase & 0x03;\n");
457             Output(Out, "if ((ULONG)(BltInfo->DestRect.right - BltInfo->DestRect.left) < "
458                    "LeftCount)\n");
459             Output(Out, "{\n");
460             Output(Out, "LeftCount = BltInfo->DestRect.right - "
461                    "BltInfo->DestRect.left;\n");
462             Output(Out, "}\n");
463         }
464         Output(Out, "CenterCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
465         Output(Out, "               LeftCount) / %u;\n", 32 / Bpp);
466         Output(Out, "RightCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
467         Output(Out, "              LeftCount - %u * CenterCount);\n", 32 / Bpp);
468     }
469     else
470     {
471         Output(Out, "CenterCount = BltInfo->DestRect.right - BltInfo->DestRect.left;\n");
472     }
473 }
474 
475 static void
476 CreateSetSinglePixel(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
477                      unsigned SourceBpp)
478 {
479     if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
480     {
481         CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp, 0);
482         MARK(Out);
483     }
484     if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
485     {
486         Output(Out, "Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, PatternX, PatternY);\n");
487         Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
488         Output(Out, "{\n");
489         Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
490         Output(Out, "}\n");
491     }
492     if ((RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE) &&
493             Bpp != SourceBpp) ||
494             (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE)))
495     {
496         Output(Out, "\n");
497     }
498     CreateOperation(Out, Bpp, RopInfo, SourceBpp, 16);
499     Output(Out, ";\n");
500     MARK(Out);
501     Output(Out, "\n");
502     Output(Out, "DestPtr = (PULONG)((char *) DestPtr + %u);\n", Bpp / 8);
503 }
504 
505 static void
506 CreateBitCase(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
507               unsigned SourceBpp)
508 {
509     unsigned Partial;
510 
511     MARK(Out);
512     if (RopInfo->UsesSource)
513     {
514         if (0 == (Flags & FLAG_FORCENOUSESSOURCE))
515         {
516             CreateBase(Out, 1, Flags, SourceBpp);
517         }
518         CreateBase(Out, 0, Flags, Bpp);
519         CreateCounts(Out, Bpp);
520         MARK(Out);
521     }
522     if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
523     {
524         if (0 == (Flags & FLAG_BOTTOMUP))
525         {
526             Output(Out, "PatternY = (BltInfo->DestRect.top - BltInfo->BrushOrigin.y) %%\n");
527             Output(Out, "           BltInfo->PatternSurface->sizlBitmap.cy;\n");
528         }
529         else
530         {
531             Output(Out, "PatternY = (BltInfo->DestRect.bottom - 1 -\n");
532             Output(Out, "            BltInfo->BrushOrigin.y) %%\n");
533             Output(Out, "           BltInfo->PatternSurface->sizlBitmap.cy;\n");
534         }
535     }
536     if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
537             0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
538     {
539         Output(Out, "CenterCount = %u * (BltInfo->DestRect.right -\n", Bpp >> 3);
540         Output(Out, "                   BltInfo->DestRect.left);\n");
541     }
542     if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
543     {
544         Output(Out, "BasePatternX = (BltInfo->DestRect.left - BltInfo->BrushOrigin.x) %%\n");
545         Output(Out, "           BltInfo->PatternSurface->sizlBitmap.cx;\n");
546     }
547 
548     Output(Out, "for (LineIndex = 0; LineIndex < LineCount; LineIndex++)\n");
549     Output(Out, "{\n");
550     if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
551             0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
552     {
553         if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
554         {
555             Output(Out, "SourcePtr = (PULONG) SourceBase;\n");
556             if (SourceBpp <= 16)
557             {
558                 Output(Out, "RawSource = *SourcePtr++;\n");
559                 Output(Out, "SourcePixels = BaseSourcePixels;\n");
560             }
561         }
562         Output(Out, "DestPtr = (PULONG) DestBase;\n");
563     }
564 
565     if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
566     {
567         Output(Out, "PatternX = BasePatternX;\n");
568     }
569 
570     if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
571             0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
572     {
573         Output(Out, "RtlMoveMemory(DestBase, SourceBase, CenterCount);\n");
574         Output(Out, "\n");
575     }
576     else
577     {
578         Output(Out, "\n");
579         if (32 != Bpp)
580         {
581             if (16 == Bpp)
582             {
583                 Output(Out, "if (0 != LeftCount)\n");
584             }
585             else
586             {
587                 Output(Out, "for (i = 0; i < LeftCount; i++)\n");
588             }
589             Output(Out, "{\n");
590             CreateSetSinglePixel(Out, Bpp, RopInfo,
591                                  (16 == Bpp ? Flags | FLAG_FORCERAWSOURCEAVAIL :
592                                   Flags), SourceBpp);
593             MARK(Out);
594             Output(Out, "}\n");
595             Output(Out, "\n");
596         }
597         Output(Out, "for (i = 0; i < CenterCount; i++)\n");
598         Output(Out, "{\n");
599         if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
600         {
601             for (Partial = 0; Partial < 32 / Bpp; Partial++)
602             {
603                 CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp,
604                                 Partial * Bpp);
605                 MARK(Out);
606             }
607             Output(Out, "\n");
608         }
609         if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
610         {
611             for (Partial = 0; Partial < 32 / Bpp; Partial++)
612             {
613                 if (0 == Partial)
614                 {
615                     Output(Out, "Pattern = DIB_GetSourceIndex(BltInfo->PatternSurface, PatternX, PatternY);\n");
616                 }
617                 else
618                 {
619                     Output(Out, "Pattern |= DIB_GetSourceIndex(BltInfo->PatternSurface, PatternX, PatternY) << %u;\n", Partial * Bpp);
620                 }
621                 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
622                 Output(Out, "{\n");
623                 Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
624                 Output(Out, "}\n");
625             }
626             Output(Out, "\n");
627         }
628         CreateOperation(Out, Bpp, RopInfo, SourceBpp, 32);
629         Output(Out, ";\n");
630         MARK(Out);
631         Output(Out, "\n");
632         Output(Out, "DestPtr++;\n");
633         Output(Out, "}\n");
634         Output(Out, "\n");
635         if (32 != Bpp)
636         {
637             if (16 == Bpp)
638             {
639                 Output(Out, "if (0 != RightCount)\n");
640             }
641             else
642             {
643                 Output(Out, "for (i = 0; i < RightCount; i++)\n");
644             }
645             Output(Out, "{\n");
646             CreateSetSinglePixel(Out, Bpp, RopInfo, Flags, SourceBpp);
647             MARK(Out);
648             Output(Out, "}\n");
649             Output(Out, "\n");
650         }
651         if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
652         {
653             if (0 == (Flags & FLAG_BOTTOMUP))
654             {
655                 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cy <= ++PatternY)\n");
656                 Output(Out, "{\n");
657                 Output(Out, "PatternY -= BltInfo->PatternSurface->sizlBitmap.cy;\n");
658                 Output(Out, "}\n");
659             }
660             else
661             {
662                 Output(Out, "if (0 == PatternY--)\n");
663                 Output(Out, "{\n");
664                 Output(Out, "PatternY = BltInfo->PatternSurface->sizlBitmap.cy - 1;\n");
665                 Output(Out, "}\n");
666             }
667         }
668     }
669     if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
670     {
671         Output(Out, "SourceBase %c= BltInfo->SourceSurface->lDelta;\n",
672                0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
673     }
674     Output(Out, "DestBase %c= BltInfo->DestSurface->lDelta;\n",
675            0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
676     Output(Out, "}\n");
677 }
678 
679 static void
680 CreateActionBlock(FILE *Out, unsigned Bpp, PROPINFO RopInfo,
681                   int Flags)
682 {
683     static unsigned SourceBpp[ ] =
684     { 1, 4, 8, 16, 24, 32 };
685     unsigned BppIndex;
686 
687     MARK(Out);
688     if (RopInfo->UsesSource)
689     {
690         if (ROPCODE_GENERIC == RopInfo->RopCode)
691         {
692             Output(Out, "if (UsesSource)\n");
693             Output(Out, "{\n");
694         }
695         Output(Out, "switch (BltInfo->SourceSurface->iBitmapFormat)\n");
696         Output(Out, "{\n");
697         for (BppIndex = 0;
698                 BppIndex < sizeof(SourceBpp) / sizeof(unsigned);
699                 BppIndex++)
700         {
701             Output(Out, "case BMF_%uBPP:\n", SourceBpp[BppIndex]);
702             Output(Out, "{\n");
703             if (Bpp == SourceBpp[BppIndex])
704             {
705                 Output(Out, "if (NULL == BltInfo->XlateSourceToDest ||\n");
706                 Output(Out, "    0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))\n");
707                 Output(Out, "{\n");
708                 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
709                 Output(Out, "{\n");
710                 CreateBitCase(Out, Bpp, RopInfo,
711                               Flags | FLAG_TRIVIALXLATE,
712                               SourceBpp[BppIndex]);
713                 MARK(Out);
714                 Output(Out, "}\n");
715                 Output(Out, "else\n");
716                 Output(Out, "{\n");
717                 CreateBitCase(Out, Bpp, RopInfo,
718                               Flags | FLAG_BOTTOMUP | FLAG_TRIVIALXLATE,
719                               SourceBpp[BppIndex]);
720                 MARK(Out);
721                 Output(Out, "}\n");
722                 Output(Out, "}\n");
723                 Output(Out, "else\n");
724                 Output(Out, "{\n");
725                 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
726                 Output(Out, "{\n");
727                 CreateBitCase(Out, Bpp, RopInfo, Flags, SourceBpp[BppIndex]);
728                 MARK(Out);
729                 Output(Out, "}\n");
730                 Output(Out, "else\n");
731                 Output(Out, "{\n");
732                 CreateBitCase(Out, Bpp, RopInfo,
733                               Flags | FLAG_BOTTOMUP,
734                               SourceBpp[BppIndex]);
735                 MARK(Out);
736                 Output(Out, "}\n");
737                 Output(Out, "}\n");
738             }
739             else
740             {
741                 CreateBitCase(Out, Bpp, RopInfo, Flags,
742                               SourceBpp[BppIndex]);
743                 MARK(Out);
744             }
745             Output(Out, "break;\n");
746             Output(Out, "}\n");
747         }
748         Output(Out, "}\n");
749         if (ROPCODE_GENERIC == RopInfo->RopCode)
750         {
751             Output(Out, "}\n");
752             Output(Out, "else\n");
753             Output(Out, "{\n");
754             CreateBitCase(Out, Bpp, RopInfo, Flags | FLAG_FORCENOUSESSOURCE, 0);
755             MARK(Out);
756             Output(Out, "}\n");
757         }
758     }
759     else
760     {
761         CreateBitCase(Out, Bpp, RopInfo, Flags, 0);
762     }
763 }
764 
765 static void
766 CreatePrimitive(FILE *Out, unsigned Bpp, PROPINFO RopInfo)
767 {
768     int First;
769     unsigned Partial;
770 
771     MARK(Out);
772     Output(Out, "\n");
773     Output(Out, "static void\n");
774     PrintRoutineName(Out, Bpp, RopInfo);
775     Output(Out, "(PBLTINFO BltInfo)\n");
776     Output(Out, "{\n");
777     if (ROPCODE_BLACKNESS == RopInfo->RopCode)
778     {
779         Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
780                "&BltInfo->DestRect, 0x0);\n", Bpp);
781     }
782     else if (ROPCODE_WHITENESS == RopInfo->RopCode)
783     {
784         Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
785                "&BltInfo->DestRect, ~0);\n", Bpp);
786     }
787     else if (ROPCODE_NOOP == RopInfo->RopCode)
788     {
789         Output(Out, "return;\n");
790     }
791     else
792     {
793         Output(Out, "ULONG LineIndex, LineCount;\n");
794         Output(Out, "ULONG i;\n");
795         if (RopInfo->UsesPattern)
796         {
797             Output(Out, "LONG PatternX =0, PatternY = 0, BasePatternX = 0;\n");
798         }
799         First = 1;
800         if (RopInfo->UsesSource)
801         {
802             Output(Out, "ULONG Source = 0");
803             First = 0;
804         }
805         if (RopInfo->UsesPattern)
806         {
807             Output(Out, "%s Pattern = 0", First ? "ULONG" : ",");
808             First = 0;
809         }
810         if (! First)
811         {
812             Output(Out, ";\n");
813         }
814         Output(Out, "char *DestBase;\n");
815         Output(Out, "PULONG DestPtr;\n");
816         if (RopInfo->UsesSource)
817         {
818             Output(Out, "char *SourceBase;\n");
819             Output(Out, "PULONG SourcePtr;\n");
820             Output(Out, "ULONG RawSource;\n");
821             Output(Out, "unsigned SourcePixels, BaseSourcePixels;\n");
822         }
823         if (32 == Bpp)
824         {
825             Output(Out, "ULONG CenterCount;\n");
826         }
827         else
828         {
829             Output(Out, "ULONG LeftCount, CenterCount, RightCount;\n");
830         }
831         if (ROPCODE_GENERIC == RopInfo->RopCode)
832         {
833             Output(Out, "BOOLEAN UsesSource, UsesPattern;\n");
834             Output(Out, "\n");
835             Output(Out, "UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);\n");
836             Output(Out, "UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);\n");
837         }
838         Output(Out, "\n");
839         if (! RopInfo->UsesSource)
840         {
841             CreateBase(Out, 0, 0, Bpp);
842             CreateCounts(Out, Bpp);
843             MARK(Out);
844         }
845         Output(Out, "LineCount = BltInfo->DestRect.bottom - BltInfo->DestRect.top;\n");
846 
847         Output(Out, "\n");
848         if (RopInfo->UsesPattern)
849         {
850             if (ROPCODE_GENERIC == RopInfo->RopCode)
851             {
852                 Output(Out, "if (UsesPattern && NULL != BltInfo->PatternSurface)\n");
853             }
854             else
855             {
856                 Output(Out, "if (NULL != BltInfo->PatternSurface)\n");
857             }
858             Output(Out, "{\n");
859             CreateActionBlock(Out, Bpp, RopInfo, FLAG_PATTERNSURFACE);
860             MARK(Out);
861             Output(Out, "}\n");
862             Output(Out, "else\n");
863             Output(Out, "{\n");
864             if (ROPCODE_GENERIC == RopInfo->RopCode)
865             {
866                 Output(Out, "if (UsesPattern)\n");
867                 Output(Out, "{\n");
868             }
869             for (Partial = 0; Partial < 32 / Bpp; Partial++)
870             {
871                 if (0 == Partial)
872                 {
873                     Output(Out, "if (!BltInfo->Brush)\n");
874                     Output(Out, "{\n");
875                     Output(Out, "Pattern = 0;\n");
876                     Output(Out, "}\n");
877                     Output(Out, "else\n");
878                     Output(Out, "{\n");
879                     Output(Out, "Pattern = BltInfo->Brush->iSolidColor");
880                 }
881                 else
882                 {
883                     Output(Out, "          (BltInfo->Brush->iSolidColor << %d)",
884                            Partial * Bpp);
885                 }
886                 if (32 / Bpp <= Partial + 1)
887                 {
888                     Output(Out, ";\n");
889                     Output(Out, "}\n");
890                 }
891                 else
892                 {
893                     Output(Out, " |\n");
894                 }
895             }
896             if (ROPCODE_PATINVERT == RopInfo->RopCode ||
897                     ROPCODE_MERGECOPY == RopInfo->RopCode)
898             {
899                 Output(Out, "if (0 == Pattern)\n");
900                 Output(Out, "{\n");
901                 if (ROPCODE_MERGECOPY == RopInfo->RopCode)
902                 {
903                     Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
904                            "&BltInfo->DestRect, 0x0);\n", Bpp);
905                 }
906                 Output(Out, "return;\n");
907                 Output(Out, "}\n");
908             }
909             else if (ROPCODE_PATPAINT == RopInfo->RopCode)
910             {
911                 Output(Out, "if ((~0) == Pattern)\n");
912                 Output(Out, "{\n");
913                 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
914                        "&BltInfo->DestRect, ~0);\n", Bpp);
915                 Output(Out, "return;\n");
916                 Output(Out, "}\n");
917             }
918             if (ROPCODE_GENERIC == RopInfo->RopCode)
919             {
920                 Output(Out, "}\n");
921             }
922             CreateActionBlock(Out, Bpp, RopInfo, 0);
923             MARK(Out);
924             Output(Out, "}\n");
925         }
926         else
927         {
928             CreateActionBlock(Out, Bpp, RopInfo, 0);
929             MARK(Out);
930         }
931     }
932     Output(Out, "}\n");
933 }
934 
935 static void
936 CreateTable(FILE *Out, unsigned Bpp)
937 {
938     unsigned RopCode;
939 
940     MARK(Out);
941     Output(Out, "\n");
942     Output(Out, "static void (*PrimitivesTable[256])(PBLTINFO) =\n");
943     Output(Out, "{\n");
944     for (RopCode = 0; RopCode < 256; RopCode++)
945     {
946         PrintRoutineName(Out, Bpp, FindRopInfo(RopCode));
947         if (RopCode < 255)
948         {
949             Output(Out, ",");
950         }
951         Output(Out, "\n");
952     }
953     Output(Out, "};\n");
954 }
955 
956 static void
957 CreateBitBlt(FILE *Out, unsigned Bpp)
958 {
959     MARK(Out);
960     Output(Out, "\n");
961     Output(Out, "BOOLEAN\n");
962     Output(Out, "DIB_%uBPP_BitBlt(PBLTINFO BltInfo)\n", Bpp);
963     Output(Out, "{\n");
964     Output(Out, "PrimitivesTable[BltInfo->Rop4 & 0xff](BltInfo);\n");
965     Output(Out, "\n");
966     Output(Out, "return TRUE;\n");
967     Output(Out, "}\n");
968 }
969 
970 static void
971 Generate(char *OutputDir, unsigned Bpp)
972 {
973     FILE *Out;
974     unsigned RopCode;
975     PROPINFO RopInfo;
976     char *FileName;
977 
978     FileName = malloc(strlen(OutputDir) + 12);
979     if (NULL == FileName)
980     {
981         fprintf(stderr, "Out of memory\n");
982         exit(1);
983     }
984     strcpy(FileName, OutputDir);
985     if ('/' != FileName[strlen(FileName) - 1])
986     {
987         strcat(FileName, "/");
988     }
989     sprintf(FileName + strlen(FileName), "dib%ugen.c", Bpp);
990 
991     Out = fopen(FileName, "w");
992     free(FileName);
993     if (NULL == Out)
994     {
995         perror("Error opening output file");
996         exit(1);
997     }
998 
999     MARK(Out);
1000     Output(Out, "/* This is a generated file. Please do not edit */\n");
1001     Output(Out, "\n");
1002     Output(Out, "#include <win32k.h>\n");
1003     CreateShiftTables(Out);
1004 
1005     RopInfo = FindRopInfo(ROPCODE_GENERIC);
1006     CreatePrimitive(Out, Bpp, RopInfo);
1007     for (RopCode = 0; RopCode < 256; RopCode++)
1008     {
1009         RopInfo = FindRopInfo(RopCode);
1010         if (NULL != RopInfo)
1011         {
1012             CreatePrimitive(Out, Bpp, RopInfo);
1013         }
1014     }
1015     CreateTable(Out, Bpp);
1016     CreateBitBlt(Out, Bpp);
1017 
1018     fclose(Out);
1019 }
1020 
1021 int
1022 main(int argc, char *argv[])
1023 {
1024     unsigned Index;
1025     static unsigned DestBpp[] =
1026     { 8, 16, 32 };
1027 
1028     if (argc < 2)
1029         return 0;
1030 
1031     for (Index = 0; Index < sizeof(DestBpp) / sizeof(DestBpp[0]); Index++)
1032     {
1033         Generate(argv[1], DestBpp[Index]);
1034     }
1035 
1036     return 0;
1037 }
1038