Add generation of 32bpp DIB code
[reactos.git] / reactos / tools / gendib / gendib.c
1 /*
2 * Copyright 2005 Ge van Geldorp (gvg@reactos.com).
3 *
4 * This program is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License as published by the
6 * Free Software Foundation; either version 2.1 of the License, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * 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 License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 char *Name;
123 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, char *Fmt, ...)
174 {
175 static unsigned Indent = 0;
176 static int AtBOL = 1;
177 unsigned n;
178 va_list Args;
179
180 if (NULL != strchr(Fmt, '{') && 0 != Indent)
181 {
182 Indent += 2;
183 }
184 else if (NULL != strchr(Fmt, '}'))
185 {
186 Indent -= 2;
187 }
188 if (AtBOL)
189 {
190 for (n = 0; n < Indent; n++)
191 {
192 putc(' ', Out);
193 }
194 AtBOL = 0;
195 }
196
197 va_start(Args, Fmt);
198 vfprintf(Out, Fmt, Args);
199 va_end(Args);
200
201 if (NULL != strchr(Fmt, '{'))
202 {
203 Indent += 2;
204 }
205 else if (NULL != strchr(Fmt, '}') && 0 != Indent)
206 {
207 Indent -= 2;
208 }
209 AtBOL = '\n' == Fmt[strlen(Fmt) - 1];
210 }
211
212 static void
213 PrintRoutineName(FILE *Out, unsigned Bpp, PROPINFO RopInfo)
214 {
215 if (NULL != RopInfo && ROPCODE_GENERIC != RopInfo->RopCode)
216 {
217 Output(Out, "DIB_%uBPP_BitBlt_%s", Bpp, RopInfo->Name);
218 }
219 else
220 {
221 Output(Out, "DIB_%uBPP_BitBlt_Generic", Bpp);
222 }
223 }
224
225 static void
226 CreateShiftTables(FILE *Out)
227 {
228 Output(Out, "\n");
229 Output(Out, "static unsigned Shift1Bpp[] =\n");
230 Output(Out, "{\n");
231 Output(Out, "0,\n");
232 Output(Out, "24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23,\n");
233 Output(Out, "8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7\n");
234 Output(Out, "};\n");
235 Output(Out, "static unsigned Shift4Bpp[] =\n");
236 Output(Out, "{\n");
237 Output(Out, "0,\n");
238 Output(Out, "24, 28, 16, 20, 8, 12, 0, 4\n");
239 Output(Out, "};\n");
240 Output(Out, "static unsigned Shift8Bpp[] =\n");
241 Output(Out, "{\n");
242 Output(Out, "0,\n");
243 Output(Out, "24, 16, 8, 0\n");
244 Output(Out, "};\n");
245 Output(Out, "static unsigned Shift16Bpp[] =\n");
246 Output(Out, "{\n");
247 Output(Out, "0,\n");
248 Output(Out, "16, 0\n");
249 Output(Out, "};\n");
250 }
251
252 static void
253 CreateOperation(FILE *Out, unsigned Bpp, PROPINFO RopInfo, unsigned SourceBpp,
254 unsigned Bits)
255 {
256 char *Cast;
257 char *Dest;
258 char *Template;
259
260 MARK(Out);
261 if (32 == Bits)
262 {
263 Cast = "";
264 Dest = "*DestPtr";
265 }
266 else
267 {
268 Cast = "(USHORT) ";
269 Dest = "*((PUSHORT) DestPtr)";
270 }
271 Output(Out, "%s = ", Dest);
272 if (ROPCODE_GENERIC == RopInfo->RopCode)
273 {
274 Output(Out, "%sDIB_DoRop(BltInfo->Rop4, %s, Source, Pattern)",
275 Cast, Dest);
276 }
277 else
278 {
279 Template = RopInfo->Operation;
280 while ('\0' != *Template)
281 {
282 switch(*Template)
283 {
284 case 'S':
285 Output(Out, "%sSource", Cast);
286 break;
287 case 'P':
288 Output(Out, "%sPattern", Cast);
289 break;
290 case 'D':
291 Output(Out, "%s", Dest);
292 break;
293 default:
294 Output(Out, "%c", *Template);
295 break;
296 }
297 Template++;
298 }
299 }
300 }
301
302 static void
303 CreateBase(FILE *Out, int Source, int Flags, unsigned Bpp)
304 {
305 char *What = (Source ? "Source" : "Dest");
306
307 MARK(Out);
308 Output(Out, "%sBase = (char *) BltInfo->%sSurface->pvScan0 +\n", What, What);
309 if (0 == (Flags & FLAG_BOTTOMUP))
310 {
311 if (Source)
312 {
313 Output(Out, " BltInfo->SourcePoint.y *\n");
314 }
315 else
316 {
317 Output(Out, " BltInfo->DestRect.top *\n");
318 }
319 }
320 else
321 {
322 if (Source)
323 {
324 Output(Out, " (BltInfo->SourcePoint.y +\n");
325 Output(Out, " BltInfo->DestRect.bottom -\n");
326 Output(Out, " BltInfo->DestRect.top - 1) *\n");
327 }
328 else
329 {
330 Output(Out, " (BltInfo->DestRect.bottom - 1) *\n");
331 }
332 }
333 Output(Out, " %sBltInfo->%sSurface->lDelta +\n",
334 Source ? " " : "", What);
335 if (Source)
336 {
337 Output(Out, " %sBltInfo->SourcePoint.x",
338 16 < Bpp ? "" : "((");
339 }
340 else
341 {
342 Output(Out, " BltInfo->DestRect.left");
343 }
344 if (Bpp < 8)
345 {
346 Output(Out, " / %u", 8 / Bpp);
347 }
348 else if (8 < Bpp)
349 {
350 Output(Out, " * %u", Bpp / 8);
351 }
352 if (Source && Bpp <= 16)
353 {
354 Output(Out, ") & ~ 0x3)");
355 }
356 Output(Out, ";\n", Bpp / 8);
357 if (Source && Bpp <= 16)
358 {
359 Output(Out, "BaseSourcePixels = %u - (BltInfo->SourcePoint.x & 0x%x);\n",
360 32 / Bpp, 32 / Bpp - 1);
361 }
362 }
363
364 static void
365 CreateGetSource(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
366 unsigned SourceBpp, unsigned Shift)
367 {
368 char *AssignOp;
369 char *Before;
370 char After[8];
371
372 MARK(Out);
373 if (0 == Shift)
374 {
375 AssignOp = "=";
376 Before = "";
377 After[0] = '\0';
378 }
379 else
380 {
381 AssignOp = "|=";
382 Before = "(";
383 sprintf(After, ") << %u", Shift);
384 }
385
386 if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
387 0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
388 {
389 if (0 == (Flags & FLAG_FORCERAWSOURCEAVAIL) && SourceBpp <= 16)
390 {
391 Output(Out, "if (0 == SourcePixels)\n");
392 Output(Out, "{\n");
393 Output(Out, "RawSource = *SourcePtr++;\n");
394 Output(Out, "SourcePixels = %u;\n", 32 / SourceBpp);
395 Output(Out, "}\n");
396 }
397 Output(Out, "Source %s (%s", AssignOp, Before);
398 if (0 == (Flags & FLAG_TRIVIALXLATE))
399 {
400 Output(Out, "XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, %s",
401 16 < SourceBpp ? "" : "(");
402 }
403 if (32 == SourceBpp)
404 {
405 Output(Out, "*SourcePtr++");
406 }
407 else if (24 == SourceBpp)
408 {
409 Output(Out, "*(PUSHORT) SourcePtr + (*((PBYTE) SourcePtr + 2) << 16)");
410 }
411 else
412 {
413 Output(Out, "RawSource >> Shift%uBpp[SourcePixels]", SourceBpp);
414 }
415 if (0 == (Flags & FLAG_TRIVIALXLATE))
416 {
417 if (16 < SourceBpp)
418 {
419 Output(Out, ")");
420 }
421 else
422 {
423 Output(Out, ") & 0x%x)", (1 << SourceBpp) - 1);
424 }
425 }
426 if (32 == Bpp)
427 {
428 Output(Out, ")%s;\n", After);
429 }
430 else
431 {
432 Output(Out, " & 0x%x)%s;\n", (1 << Bpp) - 1, After);
433 }
434 if (SourceBpp <= 16)
435 {
436 Output(Out, "SourcePixels--;\n");
437 }
438 else if (24 == SourceBpp)
439 {
440 Output(Out, "SourcePtr = (PULONG)((char *) SourcePtr + 3);\n");
441 }
442 }
443 }
444
445 static void
446 CreateCounts(FILE *Out, unsigned Bpp)
447 {
448 MARK(Out);
449 if (32 != Bpp)
450 {
451 Output(Out, "LeftCount = ((ULONG_PTR) DestBase >> 1) & 0x01;\n");
452 Output(Out, "CenterCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
453 Output(Out, " LeftCount) / 2;\n");
454 Output(Out, "RightCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
455 Output(Out, " LeftCount - 2 * CenterCount);\n");
456 }
457 else
458 {
459 Output(Out, "CenterCount = BltInfo->DestRect.right - BltInfo->DestRect.left;\n");
460 }
461 }
462
463 static void
464 CreateBitCase(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
465 unsigned SourceBpp)
466 {
467 unsigned Partial;
468
469 MARK(Out);
470 if (RopInfo->UsesSource)
471 {
472 if (0 == (Flags & FLAG_FORCENOUSESSOURCE))
473 {
474 CreateBase(Out, 1, Flags, SourceBpp);
475 }
476 CreateBase(Out, 0, Flags, Bpp);
477 CreateCounts(Out, Bpp);
478 MARK(Out);
479 }
480 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
481 {
482 if (0 == (Flags & FLAG_BOTTOMUP))
483 {
484 Output(Out, "PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %%\n");
485 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cy;\n");
486 }
487 else
488 {
489 Output(Out, "PatternY = (BltInfo->DestRect.bottom - 1 +\n");
490 Output(Out, " BltInfo->BrushOrigin.y) %%\n");
491 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cy;\n");
492 }
493 }
494 if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
495 0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
496 {
497 Output(Out, "CenterCount = 2 * (BltInfo->DestRect.right -\n");
498 Output(Out, " BltInfo->DestRect.left);\n");
499 }
500 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
501 {
502 Output(Out, "BasePatternX = (BltInfo->DestRect.left + BltInfo->BrushOrigin.x) %%\n");
503 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cx;\n");
504 }
505
506 Output(Out, "for (LineIndex = 0; LineIndex < LineCount; LineIndex++)\n");
507 Output(Out, "{\n");
508 if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
509 0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
510 {
511 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
512 {
513 Output(Out, "SourcePtr = (PULONG) SourceBase;\n");
514 if (SourceBpp <= 16)
515 {
516 Output(Out, "RawSource = *SourcePtr++;\n");
517 Output(Out, "SourcePixels = BaseSourcePixels;\n");
518 }
519 }
520 Output(Out, "DestPtr = (PULONG) DestBase;\n");
521 }
522
523 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
524 {
525 Output(Out, "PatternX = BasePatternX;\n");
526 }
527
528 if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
529 0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
530 {
531 Output(Out, "RtlMoveMemory(DestBase, SourceBase, CenterCount);\n");
532 Output(Out, "\n");
533 }
534 else
535 {
536 Output(Out, "\n");
537 if (32 != Bpp)
538 {
539 Output(Out, "if (0 != LeftCount)\n");
540 Output(Out, "{\n");
541 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
542 {
543 CreateGetSource(Out, Bpp, RopInfo, Flags | FLAG_FORCERAWSOURCEAVAIL,
544 SourceBpp, 0);
545 MARK(Out);
546 }
547 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
548 {
549 Output(Out, "Pattern = DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest);\n");
550 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
551 Output(Out, "{\n");
552 Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
553 Output(Out, "}\n");
554 }
555 if ((RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE) &&
556 Bpp != SourceBpp) ||
557 (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE)))
558 {
559 Output(Out, "\n");
560 }
561 CreateOperation(Out, Bpp, RopInfo, SourceBpp, 16);
562 Output(Out, ";\n");
563 MARK(Out);
564 Output(Out, "\n");
565 Output(Out, "DestPtr = (PULONG)((char *) DestPtr + 2);\n");
566 Output(Out, "}\n");
567 Output(Out, "\n");
568 }
569 Output(Out, "for (i = 0; i < CenterCount; i++)\n");
570 Output(Out, "{\n");
571 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
572 {
573 for (Partial = 0; Partial < 32 / Bpp; Partial++)
574 {
575 CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp,
576 Partial * Bpp);
577 MARK(Out);
578 }
579 Output(Out, "\n");
580 }
581 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
582 {
583 for (Partial = 0; Partial < 32 / Bpp; Partial++)
584 {
585 if (0 == Partial)
586 {
587 Output(Out, "Pattern = DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest);\n");
588 }
589 else
590 {
591 Output(Out, "Pattern |= DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest) << %u;\n", Partial * Bpp);
592 }
593 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
594 Output(Out, "{\n");
595 Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
596 Output(Out, "}\n");
597 }
598 Output(Out, "\n");
599 }
600 CreateOperation(Out, Bpp, RopInfo, SourceBpp, 32);
601 Output(Out, ";\n");
602 MARK(Out);
603 Output(Out, "\n");
604 Output(Out, "DestPtr++;\n");
605 Output(Out, "}\n");
606 Output(Out, "\n");
607 if (32 != Bpp)
608 {
609 Output(Out, "if (0 != RightCount)\n");
610 Output(Out, "{\n");
611 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
612 {
613 CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp, 0);
614 MARK(Out);
615 }
616 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
617 {
618 Output(Out, "Pattern = DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest);\n");
619 }
620 if ((RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE)) ||
621 (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE)))
622 {
623 Output(Out, "\n");
624 }
625 CreateOperation(Out, Bpp, RopInfo, SourceBpp, 16);
626 Output(Out, ";\n");
627 MARK(Out);
628 Output(Out, "}\n");
629 Output(Out, "\n");
630 }
631 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
632 {
633 if (0 == (Flags & FLAG_BOTTOMUP))
634 {
635 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cy <= ++PatternY)\n");
636 Output(Out, "{\n");
637 Output(Out, "PatternY -= BltInfo->PatternSurface->sizlBitmap.cy;\n");
638 Output(Out, "}\n");
639 }
640 else
641 {
642 Output(Out, "if (0 == PatternY--)\n");
643 Output(Out, "{\n");
644 Output(Out, "PatternY = BltInfo->PatternSurface->sizlBitmap.cy - 1;\n");
645 Output(Out, "}\n");
646 }
647 }
648 }
649 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
650 {
651 Output(Out, "SourceBase %c= BltInfo->SourceSurface->lDelta;\n",
652 0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
653 }
654 Output(Out, "DestBase %c= BltInfo->DestSurface->lDelta;\n",
655 0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
656 Output(Out, "}\n");
657 }
658
659 static void
660 CreateActionBlock(FILE *Out, unsigned Bpp, PROPINFO RopInfo,
661 int Flags)
662 {
663 static unsigned SourceBpp[ ] =
664 { 1, 4, 8, 16, 24, 32 };
665 unsigned BppIndex;
666
667 MARK(Out);
668 if (RopInfo->UsesSource)
669 {
670 if (ROPCODE_GENERIC == RopInfo->RopCode)
671 {
672 Output(Out, "if (UsesSource)\n");
673 Output(Out, "{\n");
674 }
675 Output(Out, "switch (BltInfo->SourceSurface->iBitmapFormat)\n");
676 Output(Out, "{\n");
677 for (BppIndex = 0;
678 BppIndex < sizeof(SourceBpp) / sizeof(unsigned);
679 BppIndex++)
680 {
681 Output(Out, "case BMF_%uBPP:\n", SourceBpp[BppIndex]);
682 Output(Out, "{\n");
683 if (Bpp == SourceBpp[BppIndex])
684 {
685 Output(Out, "if (NULL == BltInfo->XlateSourceToDest ||\n");
686 Output(Out, " 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))\n");
687 Output(Out, "{\n");
688 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
689 Output(Out, "{\n");
690 CreateBitCase(Out, Bpp, RopInfo,
691 Flags | FLAG_TRIVIALXLATE,
692 SourceBpp[BppIndex]);
693 MARK(Out);
694 Output(Out, "}\n");
695 Output(Out, "else\n");
696 Output(Out, "{\n");
697 CreateBitCase(Out, Bpp, RopInfo,
698 Flags | FLAG_BOTTOMUP | FLAG_TRIVIALXLATE,
699 SourceBpp[BppIndex]);
700 MARK(Out);
701 Output(Out, "}\n");
702 Output(Out, "}\n");
703 Output(Out, "else\n");
704 Output(Out, "{\n");
705 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
706 Output(Out, "{\n");
707 CreateBitCase(Out, Bpp, RopInfo, Flags, SourceBpp[BppIndex]);
708 MARK(Out);
709 Output(Out, "}\n");
710 Output(Out, "else\n");
711 Output(Out, "{\n");
712 CreateBitCase(Out, Bpp, RopInfo,
713 Flags | FLAG_BOTTOMUP,
714 SourceBpp[BppIndex]);
715 MARK(Out);
716 Output(Out, "}\n");
717 Output(Out, "}\n");
718 }
719 else
720 {
721 CreateBitCase(Out, Bpp, RopInfo, Flags,
722 SourceBpp[BppIndex]);
723 MARK(Out);
724 }
725 Output(Out, "break;\n");
726 Output(Out, "}\n");
727 }
728 Output(Out, "}\n");
729 if (ROPCODE_GENERIC == RopInfo->RopCode)
730 {
731 Output(Out, "}\n");
732 Output(Out, "else\n");
733 Output(Out, "{\n");
734 CreateBitCase(Out, Bpp, RopInfo, Flags | FLAG_FORCENOUSESSOURCE, 0);
735 MARK(Out);
736 Output(Out, "}\n");
737 }
738 }
739 else
740 {
741 CreateBitCase(Out, Bpp, RopInfo, Flags, 0);
742 }
743 }
744
745 static void
746 CreatePrimitive(FILE *Out, unsigned Bpp, PROPINFO RopInfo)
747 {
748 int First;
749 unsigned Partial;
750
751 MARK(Out);
752 Output(Out, "\n");
753 Output(Out, "static void\n");
754 PrintRoutineName(Out, Bpp, RopInfo);
755 Output(Out, "(PBLTINFO BltInfo)\n");
756 Output(Out, "{\n");
757 if (ROPCODE_BLACKNESS == RopInfo->RopCode)
758 {
759 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
760 "&BltInfo->DestRect, 0x0);\n", Bpp);
761 }
762 else if (ROPCODE_WHITENESS == RopInfo->RopCode)
763 {
764 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
765 "&BltInfo->DestRect, ~0);\n", Bpp);
766 }
767 else if (ROPCODE_NOOP == RopInfo->RopCode)
768 {
769 Output(Out, "return;\n");
770 }
771 else
772 {
773 Output(Out, "ULONG LineIndex, LineCount;\n");
774 Output(Out, "ULONG i;\n");
775 if (RopInfo->UsesPattern)
776 {
777 Output(Out, "ULONG PatternX =0, PatternY = 0, BasePatternX = 0;\n");
778 }
779 First = 1;
780 if (RopInfo->UsesSource)
781 {
782 Output(Out, "ULONG Source = 0");
783 First = 0;
784 }
785 if (RopInfo->UsesPattern)
786 {
787 Output(Out, "%s Pattern = 0", First ? "ULONG" : ",");
788 First = 0;
789 }
790 if (! First)
791 {
792 Output(Out, ";\n");
793 }
794 Output(Out, "char *DestBase;\n");
795 Output(Out, "PULONG DestPtr;\n");
796 if (RopInfo->UsesSource)
797 {
798 Output(Out, "char *SourceBase;\n");
799 Output(Out, "PULONG SourcePtr;\n");
800 Output(Out, "ULONG RawSource;\n");
801 Output(Out, "unsigned SourcePixels, BaseSourcePixels;\n");
802 }
803 if (32 == Bpp)
804 {
805 Output(Out, "ULONG CenterCount;\n");
806 }
807 else
808 {
809 Output(Out, "ULONG LeftCount, CenterCount, RightCount;\n");
810 }
811 if (ROPCODE_GENERIC == RopInfo->RopCode)
812 {
813 Output(Out, "BOOLEAN UsesDest, UsesSource, UsesPattern;\n");
814 Output(Out, "\n");
815 Output(Out, "UsesDest = ROP4_USES_DEST(BltInfo->Rop4);\n");
816 Output(Out, "UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);\n");
817 Output(Out, "UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);\n");
818 }
819 Output(Out, "\n");
820 if (! RopInfo->UsesSource)
821 {
822 CreateBase(Out, 0, 0, Bpp);
823 CreateCounts(Out, Bpp);
824 MARK(Out);
825 }
826 Output(Out, "LineCount = BltInfo->DestRect.bottom - BltInfo->DestRect.top;\n");
827
828 Output(Out, "\n");
829 if (RopInfo->UsesPattern)
830 {
831 if (ROPCODE_GENERIC == RopInfo->RopCode)
832 {
833 Output(Out, "if (UsesPattern && NULL != BltInfo->PatternSurface)\n");
834 }
835 else
836 {
837 Output(Out, "if (NULL != BltInfo->PatternSurface)\n");
838 }
839 Output(Out, "{\n");
840 CreateActionBlock(Out, Bpp, RopInfo, FLAG_PATTERNSURFACE);
841 MARK(Out);
842 Output(Out, "}\n");
843 Output(Out, "else\n");
844 Output(Out, "{\n");
845 if (ROPCODE_GENERIC == RopInfo->RopCode)
846 {
847 Output(Out, "if (UsesPattern)\n");
848 Output(Out, "{\n");
849 }
850 for (Partial = 0; Partial < 32 / Bpp; Partial++)
851 {
852 if (0 == Partial)
853 {
854 Output(Out, "Pattern = BltInfo->Brush->iSolidColor");
855 }
856 else
857 {
858 Output(Out, " (BltInfo->Brush->iSolidColor << %d)",
859 Partial * Bpp);
860 }
861 if (32 / Bpp <= Partial + 1)
862 {
863 Output(Out, ";\n");
864 }
865 else
866 {
867 Output(Out, " |\n");
868 }
869 }
870 if (ROPCODE_PATINVERT == RopInfo->RopCode ||
871 ROPCODE_MERGECOPY == RopInfo->RopCode)
872 {
873 Output(Out, "if (0 == Pattern)\n");
874 Output(Out, "{\n");
875 if (ROPCODE_MERGECOPY == RopInfo->RopCode)
876 {
877 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
878 "&BltInfo->DestRect, 0x0);\n", Bpp);
879 }
880 Output(Out, "return;\n");
881 Output(Out, "}\n");
882 }
883 else if (ROPCODE_PATPAINT == RopInfo->RopCode)
884 {
885 Output(Out, "if ((~0) == Pattern)\n");
886 Output(Out, "{\n");
887 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
888 "&BltInfo->DestRect, ~0);\n", Bpp);
889 Output(Out, "return;\n");
890 Output(Out, "}\n");
891 }
892 if (ROPCODE_GENERIC == RopInfo->RopCode)
893 {
894 Output(Out, "}\n");
895 }
896 CreateActionBlock(Out, Bpp, RopInfo, 0);
897 MARK(Out);
898 Output(Out, "}\n");
899 }
900 else
901 {
902 CreateActionBlock(Out, Bpp, RopInfo, 0);
903 MARK(Out);
904 }
905 }
906 Output(Out, "}\n");
907 }
908
909 static void
910 CreateTable(FILE *Out, unsigned Bpp)
911 {
912 unsigned RopCode;
913
914 MARK(Out);
915 Output(Out, "\n");
916 Output(Out, "static void (*PrimitivesTable[256])(PBLTINFO) =\n");
917 Output(Out, " {\n");
918 for (RopCode = 0; RopCode < 256; RopCode++)
919 {
920 Output(Out, " ");
921 PrintRoutineName(Out, Bpp, FindRopInfo(RopCode));
922 if (RopCode < 255)
923 {
924 putc(',', Out);
925 }
926 putc('\n', Out);
927 }
928 Output(Out, " };\n");
929 }
930
931 static void
932 CreateBitBlt(FILE *Out, unsigned Bpp)
933 {
934 MARK(Out);
935 Output(Out, "\n");
936 Output(Out, "BOOLEAN\n");
937 Output(Out, "DIB_%uBPP_BitBlt(PBLTINFO BltInfo)\n", Bpp);
938 Output(Out, "{\n");
939 Output(Out, " PrimitivesTable[BltInfo->Rop4 & 0xff](BltInfo);\n");
940 Output(Out, "\n");
941 Output(Out, " return TRUE;\n");
942 Output(Out, "}\n");
943 }
944
945 static void
946 Generate(char *OutputDir, unsigned Bpp)
947 {
948 FILE *Out;
949 unsigned RopCode;
950 PROPINFO RopInfo;
951 char *FileName;
952
953 FileName = malloc(strlen(OutputDir) + 12);
954 if (NULL == FileName)
955 {
956 fprintf(stderr, "Out of memory\n");
957 exit(1);
958 }
959 strcpy(FileName, OutputDir);
960 if ('/' != FileName[strlen(FileName) - 1])
961 {
962 strcat(FileName, "/");
963 }
964 sprintf(FileName + strlen(FileName), "dib%ugen.c", Bpp);
965
966 Out = fopen(FileName, "w");
967 free(FileName);
968 if (NULL == Out)
969 {
970 perror("Error opening output file");
971 exit(1);
972 }
973
974 MARK(Out);
975 Output(Out, "/* This is a generated file. Please do not edit */\n");
976 Output(Out, "\n");
977 Output(Out, "#include \"w32k.h\"\n");
978 CreateShiftTables(Out);
979
980 RopInfo = FindRopInfo(ROPCODE_GENERIC);
981 CreatePrimitive(Out, Bpp, RopInfo);
982 for (RopCode = 0; RopCode < 256; RopCode++)
983 {
984 RopInfo = FindRopInfo(RopCode);
985 if (NULL != RopInfo)
986 {
987 CreatePrimitive(Out, Bpp, RopInfo);
988 }
989 }
990 CreateTable(Out, Bpp);
991 CreateBitBlt(Out, Bpp);
992
993 fclose(Out);
994 }
995
996 int
997 main(int argc, char *argv[])
998 {
999 unsigned Index;
1000 static unsigned DestBpp[] =
1001 { 16, 32 };
1002
1003 for (Index = 0; Index < sizeof(DestBpp) / sizeof(DestBpp[0]); Index++)
1004 {
1005 Generate(argv[1], DestBpp[Index]);
1006 }
1007
1008 return 0;
1009 }