f9c1383b55c448d90b722d9833afd4da4e510fbe
[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 if (16 == Bpp)
267 {
268 Cast = "(USHORT) ";
269 Dest = "*((PUSHORT) DestPtr)";
270 }
271 else
272 {
273 Cast = "(UCHAR) ";
274 Dest = "*((PUCHAR) DestPtr)";
275 }
276 Output(Out, "%s = ", Dest);
277 if (ROPCODE_GENERIC == RopInfo->RopCode)
278 {
279 Output(Out, "%sDIB_DoRop(BltInfo->Rop4, %s, Source, Pattern)",
280 Cast, Dest);
281 }
282 else
283 {
284 Template = RopInfo->Operation;
285 while ('\0' != *Template)
286 {
287 switch(*Template)
288 {
289 case 'S':
290 Output(Out, "%sSource", Cast);
291 break;
292 case 'P':
293 Output(Out, "%sPattern", Cast);
294 break;
295 case 'D':
296 Output(Out, "%s", Dest);
297 break;
298 default:
299 Output(Out, "%c", *Template);
300 break;
301 }
302 Template++;
303 }
304 }
305 }
306
307 static void
308 CreateBase(FILE *Out, int Source, int Flags, unsigned Bpp)
309 {
310 char *What = (Source ? "Source" : "Dest");
311
312 MARK(Out);
313 Output(Out, "%sBase = (char *) BltInfo->%sSurface->pvScan0 +\n", What, What);
314 if (0 == (Flags & FLAG_BOTTOMUP))
315 {
316 if (Source)
317 {
318 Output(Out, " BltInfo->SourcePoint.y *\n");
319 }
320 else
321 {
322 Output(Out, " BltInfo->DestRect.top *\n");
323 }
324 }
325 else
326 {
327 if (Source)
328 {
329 Output(Out, " (BltInfo->SourcePoint.y +\n");
330 Output(Out, " BltInfo->DestRect.bottom -\n");
331 Output(Out, " BltInfo->DestRect.top - 1) *\n");
332 }
333 else
334 {
335 Output(Out, " (BltInfo->DestRect.bottom - 1) *\n");
336 }
337 }
338 Output(Out, " %sBltInfo->%sSurface->lDelta +\n",
339 Source ? " " : "", What);
340 if (Source)
341 {
342 Output(Out, " %sBltInfo->SourcePoint.x",
343 16 < Bpp ? "" : "((");
344 }
345 else
346 {
347 Output(Out, " BltInfo->DestRect.left");
348 }
349 if (Bpp < 8)
350 {
351 Output(Out, " / %u", 8 / Bpp);
352 }
353 else if (8 < Bpp)
354 {
355 Output(Out, " * %u", Bpp / 8);
356 }
357 if (Source && Bpp <= 16)
358 {
359 Output(Out, ") & ~ 0x3)");
360 }
361 Output(Out, ";\n", Bpp / 8);
362 if (Source && Bpp <= 16)
363 {
364 Output(Out, "BaseSourcePixels = %u - (BltInfo->SourcePoint.x & 0x%x);\n",
365 32 / Bpp, 32 / Bpp - 1);
366 }
367 }
368
369 static void
370 CreateGetSource(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
371 unsigned SourceBpp, unsigned Shift)
372 {
373 char *AssignOp;
374 char *Before;
375 char After[8];
376
377 MARK(Out);
378 if (0 == Shift)
379 {
380 AssignOp = "=";
381 Before = "";
382 After[0] = '\0';
383 }
384 else
385 {
386 AssignOp = "|=";
387 Before = "(";
388 sprintf(After, ") << %u", Shift);
389 }
390
391 if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
392 0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
393 {
394 if (0 == (Flags & FLAG_FORCERAWSOURCEAVAIL) && SourceBpp <= 16)
395 {
396 Output(Out, "if (0 == SourcePixels)\n");
397 Output(Out, "{\n");
398 Output(Out, "RawSource = *SourcePtr++;\n");
399 Output(Out, "SourcePixels = %u;\n", 32 / SourceBpp);
400 Output(Out, "}\n");
401 }
402 Output(Out, "Source %s (%s", AssignOp, Before);
403 if (0 == (Flags & FLAG_TRIVIALXLATE))
404 {
405 Output(Out, "XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, %s",
406 16 < SourceBpp ? "" : "(");
407 }
408 if (32 == SourceBpp)
409 {
410 Output(Out, "*SourcePtr++");
411 }
412 else if (24 == SourceBpp)
413 {
414 Output(Out, "*(PUSHORT) SourcePtr + (*((PBYTE) SourcePtr + 2) << 16)");
415 }
416 else
417 {
418 Output(Out, "RawSource >> Shift%uBpp[SourcePixels]", SourceBpp);
419 }
420 if (0 == (Flags & FLAG_TRIVIALXLATE))
421 {
422 if (16 < SourceBpp)
423 {
424 Output(Out, ")");
425 }
426 else
427 {
428 Output(Out, ") & 0x%x)", (1 << SourceBpp) - 1);
429 }
430 }
431 if (32 == Bpp)
432 {
433 Output(Out, ")%s;\n", After);
434 }
435 else
436 {
437 Output(Out, " & 0x%x)%s;\n", (1 << Bpp) - 1, After);
438 }
439 if (SourceBpp <= 16)
440 {
441 Output(Out, "SourcePixels--;\n");
442 }
443 else if (24 == SourceBpp)
444 {
445 Output(Out, "SourcePtr = (PULONG)((char *) SourcePtr + 3);\n");
446 }
447 }
448 }
449
450 static void
451 CreateCounts(FILE *Out, unsigned Bpp)
452 {
453 MARK(Out);
454 if (32 != Bpp)
455 {
456 if (8 < Bpp)
457 {
458 Output(Out, "LeftCount = ((ULONG_PTR) DestBase >> 1) & 0x01;\n");
459 }
460 else
461 {
462 Output(Out, "LeftCount = (ULONG_PTR) DestBase & 0x03;\n");
463 Output(Out, "if (BltInfo->DestRect.right - BltInfo->DestRect.left < "
464 "LeftCount)\n");
465 Output(Out, "{\n");
466 Output(Out, "LeftCount = BltInfo->DestRect.right - "
467 "BltInfo->DestRect.left;\n");
468 Output(Out, "}\n");
469 }
470 Output(Out, "CenterCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
471 Output(Out, " LeftCount) / %u;\n", 32 / Bpp);
472 Output(Out, "RightCount = (BltInfo->DestRect.right - BltInfo->DestRect.left -\n");
473 Output(Out, " LeftCount - %u * CenterCount);\n", 32 / Bpp);
474 }
475 else
476 {
477 Output(Out, "CenterCount = BltInfo->DestRect.right - BltInfo->DestRect.left;\n");
478 }
479 }
480
481 static void
482 CreateSetSinglePixel(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
483 unsigned SourceBpp)
484 {
485 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
486 {
487 CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp, 0);
488 MARK(Out);
489 }
490 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
491 {
492 Output(Out, "Pattern = DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest);\n");
493 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
494 Output(Out, "{\n");
495 Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
496 Output(Out, "}\n");
497 }
498 if ((RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE) &&
499 Bpp != SourceBpp) ||
500 (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE)))
501 {
502 Output(Out, "\n");
503 }
504 CreateOperation(Out, Bpp, RopInfo, SourceBpp, 16);
505 Output(Out, ";\n");
506 MARK(Out);
507 Output(Out, "\n");
508 Output(Out, "DestPtr = (PULONG)((char *) DestPtr + %u);\n", Bpp / 8);
509 }
510
511 static void
512 CreateBitCase(FILE *Out, unsigned Bpp, PROPINFO RopInfo, int Flags,
513 unsigned SourceBpp)
514 {
515 unsigned Partial;
516
517 MARK(Out);
518 if (RopInfo->UsesSource)
519 {
520 if (0 == (Flags & FLAG_FORCENOUSESSOURCE))
521 {
522 CreateBase(Out, 1, Flags, SourceBpp);
523 }
524 CreateBase(Out, 0, Flags, Bpp);
525 CreateCounts(Out, Bpp);
526 MARK(Out);
527 }
528 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
529 {
530 if (0 == (Flags & FLAG_BOTTOMUP))
531 {
532 Output(Out, "PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %%\n");
533 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cy;\n");
534 }
535 else
536 {
537 Output(Out, "PatternY = (BltInfo->DestRect.bottom - 1 +\n");
538 Output(Out, " BltInfo->BrushOrigin.y) %%\n");
539 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cy;\n");
540 }
541 }
542 if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
543 0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
544 {
545 Output(Out, "CenterCount = 2 * (BltInfo->DestRect.right -\n");
546 Output(Out, " BltInfo->DestRect.left);\n");
547 }
548 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
549 {
550 Output(Out, "BasePatternX = (BltInfo->DestRect.left + BltInfo->BrushOrigin.x) %%\n");
551 Output(Out, " BltInfo->PatternSurface->sizlBitmap.cx;\n");
552 }
553
554 Output(Out, "for (LineIndex = 0; LineIndex < LineCount; LineIndex++)\n");
555 Output(Out, "{\n");
556 if (ROPCODE_SRCCOPY != RopInfo->RopCode ||
557 0 == (Flags & FLAG_TRIVIALXLATE) || Bpp != SourceBpp)
558 {
559 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
560 {
561 Output(Out, "SourcePtr = (PULONG) SourceBase;\n");
562 if (SourceBpp <= 16)
563 {
564 Output(Out, "RawSource = *SourcePtr++;\n");
565 Output(Out, "SourcePixels = BaseSourcePixels;\n");
566 }
567 }
568 Output(Out, "DestPtr = (PULONG) DestBase;\n");
569 }
570
571 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
572 {
573 Output(Out, "PatternX = BasePatternX;\n");
574 }
575
576 if (ROPCODE_SRCCOPY == RopInfo->RopCode &&
577 0 != (Flags & FLAG_TRIVIALXLATE) && Bpp == SourceBpp)
578 {
579 Output(Out, "RtlMoveMemory(DestBase, SourceBase, CenterCount);\n");
580 Output(Out, "\n");
581 }
582 else
583 {
584 Output(Out, "\n");
585 if (32 != Bpp)
586 {
587 if (16 == Bpp)
588 {
589 Output(Out, "if (0 != LeftCount)\n");
590 }
591 else
592 {
593 Output(Out, "for (i = 0; i < LeftCount; i++)\n");
594 }
595 Output(Out, "{\n");
596 CreateSetSinglePixel(Out, Bpp, RopInfo,
597 (16 == Bpp ? Flags | FLAG_FORCERAWSOURCEAVAIL :
598 Flags), SourceBpp);
599 MARK(Out);
600 Output(Out, "}\n");
601 Output(Out, "\n");
602 }
603 Output(Out, "for (i = 0; i < CenterCount; i++)\n");
604 Output(Out, "{\n");
605 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
606 {
607 for (Partial = 0; Partial < 32 / Bpp; Partial++)
608 {
609 CreateGetSource(Out, Bpp, RopInfo, Flags, SourceBpp,
610 Partial * Bpp);
611 MARK(Out);
612 }
613 Output(Out, "\n");
614 }
615 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
616 {
617 for (Partial = 0; Partial < 32 / Bpp; Partial++)
618 {
619 if (0 == Partial)
620 {
621 Output(Out, "Pattern = DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest);\n");
622 }
623 else
624 {
625 Output(Out, "Pattern |= DIB_GetSource(BltInfo->PatternSurface, PatternX, PatternY, BltInfo->XlatePatternToDest) << %u;\n", Partial * Bpp);
626 }
627 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cx <= ++PatternX)\n");
628 Output(Out, "{\n");
629 Output(Out, "PatternX -= BltInfo->PatternSurface->sizlBitmap.cx;\n");
630 Output(Out, "}\n");
631 }
632 Output(Out, "\n");
633 }
634 CreateOperation(Out, Bpp, RopInfo, SourceBpp, 32);
635 Output(Out, ";\n");
636 MARK(Out);
637 Output(Out, "\n");
638 Output(Out, "DestPtr++;\n");
639 Output(Out, "}\n");
640 Output(Out, "\n");
641 if (32 != Bpp)
642 {
643 if (16 == Bpp)
644 {
645 Output(Out, "if (0 != RightCount)\n");
646 }
647 else
648 {
649 Output(Out, "for (i = 0; i < RightCount; i++)\n");
650 }
651 Output(Out, "{\n");
652 CreateSetSinglePixel(Out, Bpp, RopInfo, Flags, SourceBpp);
653 MARK(Out);
654 Output(Out, "}\n");
655 Output(Out, "\n");
656 }
657 if (RopInfo->UsesPattern && 0 != (Flags & FLAG_PATTERNSURFACE))
658 {
659 if (0 == (Flags & FLAG_BOTTOMUP))
660 {
661 Output(Out, "if (BltInfo->PatternSurface->sizlBitmap.cy <= ++PatternY)\n");
662 Output(Out, "{\n");
663 Output(Out, "PatternY -= BltInfo->PatternSurface->sizlBitmap.cy;\n");
664 Output(Out, "}\n");
665 }
666 else
667 {
668 Output(Out, "if (0 == PatternY--)\n");
669 Output(Out, "{\n");
670 Output(Out, "PatternY = BltInfo->PatternSurface->sizlBitmap.cy - 1;\n");
671 Output(Out, "}\n");
672 }
673 }
674 }
675 if (RopInfo->UsesSource && 0 == (Flags & FLAG_FORCENOUSESSOURCE))
676 {
677 Output(Out, "SourceBase %c= BltInfo->SourceSurface->lDelta;\n",
678 0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
679 }
680 Output(Out, "DestBase %c= BltInfo->DestSurface->lDelta;\n",
681 0 == (Flags & FLAG_BOTTOMUP) ? '+' : '-');
682 Output(Out, "}\n");
683 }
684
685 static void
686 CreateActionBlock(FILE *Out, unsigned Bpp, PROPINFO RopInfo,
687 int Flags)
688 {
689 static unsigned SourceBpp[ ] =
690 { 1, 4, 8, 16, 24, 32 };
691 unsigned BppIndex;
692
693 MARK(Out);
694 if (RopInfo->UsesSource)
695 {
696 if (ROPCODE_GENERIC == RopInfo->RopCode)
697 {
698 Output(Out, "if (UsesSource)\n");
699 Output(Out, "{\n");
700 }
701 Output(Out, "switch (BltInfo->SourceSurface->iBitmapFormat)\n");
702 Output(Out, "{\n");
703 for (BppIndex = 0;
704 BppIndex < sizeof(SourceBpp) / sizeof(unsigned);
705 BppIndex++)
706 {
707 Output(Out, "case BMF_%uBPP:\n", SourceBpp[BppIndex]);
708 Output(Out, "{\n");
709 if (Bpp == SourceBpp[BppIndex])
710 {
711 Output(Out, "if (NULL == BltInfo->XlateSourceToDest ||\n");
712 Output(Out, " 0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))\n");
713 Output(Out, "{\n");
714 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
715 Output(Out, "{\n");
716 CreateBitCase(Out, Bpp, RopInfo,
717 Flags | FLAG_TRIVIALXLATE,
718 SourceBpp[BppIndex]);
719 MARK(Out);
720 Output(Out, "}\n");
721 Output(Out, "else\n");
722 Output(Out, "{\n");
723 CreateBitCase(Out, Bpp, RopInfo,
724 Flags | FLAG_BOTTOMUP | FLAG_TRIVIALXLATE,
725 SourceBpp[BppIndex]);
726 MARK(Out);
727 Output(Out, "}\n");
728 Output(Out, "}\n");
729 Output(Out, "else\n");
730 Output(Out, "{\n");
731 Output(Out, "if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)\n");
732 Output(Out, "{\n");
733 CreateBitCase(Out, Bpp, RopInfo, Flags, SourceBpp[BppIndex]);
734 MARK(Out);
735 Output(Out, "}\n");
736 Output(Out, "else\n");
737 Output(Out, "{\n");
738 CreateBitCase(Out, Bpp, RopInfo,
739 Flags | FLAG_BOTTOMUP,
740 SourceBpp[BppIndex]);
741 MARK(Out);
742 Output(Out, "}\n");
743 Output(Out, "}\n");
744 }
745 else
746 {
747 CreateBitCase(Out, Bpp, RopInfo, Flags,
748 SourceBpp[BppIndex]);
749 MARK(Out);
750 }
751 Output(Out, "break;\n");
752 Output(Out, "}\n");
753 }
754 Output(Out, "}\n");
755 if (ROPCODE_GENERIC == RopInfo->RopCode)
756 {
757 Output(Out, "}\n");
758 Output(Out, "else\n");
759 Output(Out, "{\n");
760 CreateBitCase(Out, Bpp, RopInfo, Flags | FLAG_FORCENOUSESSOURCE, 0);
761 MARK(Out);
762 Output(Out, "}\n");
763 }
764 }
765 else
766 {
767 CreateBitCase(Out, Bpp, RopInfo, Flags, 0);
768 }
769 }
770
771 static void
772 CreatePrimitive(FILE *Out, unsigned Bpp, PROPINFO RopInfo)
773 {
774 int First;
775 unsigned Partial;
776
777 MARK(Out);
778 Output(Out, "\n");
779 Output(Out, "static void\n");
780 PrintRoutineName(Out, Bpp, RopInfo);
781 Output(Out, "(PBLTINFO BltInfo)\n");
782 Output(Out, "{\n");
783 if (ROPCODE_BLACKNESS == RopInfo->RopCode)
784 {
785 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
786 "&BltInfo->DestRect, 0x0);\n", Bpp);
787 }
788 else if (ROPCODE_WHITENESS == RopInfo->RopCode)
789 {
790 Output(Out, "DIB_%uBPP_ColorFill(BltInfo->DestSurface, "
791 "&BltInfo->DestRect, ~0);\n", Bpp);
792 }
793 else if (ROPCODE_NOOP == RopInfo->RopCode)
794 {
795 Output(Out, "return;\n");
796 }
797 else
798 {
799 Output(Out, "ULONG LineIndex, LineCount;\n");
800 Output(Out, "ULONG i;\n");
801 if (RopInfo->UsesPattern)
802 {
803 Output(Out, "ULONG PatternX =0, PatternY = 0, BasePatternX = 0;\n");
804 }
805 First = 1;
806 if (RopInfo->UsesSource)
807 {
808 Output(Out, "ULONG Source = 0");
809 First = 0;
810 }
811 if (RopInfo->UsesPattern)
812 {
813 Output(Out, "%s Pattern = 0", First ? "ULONG" : ",");
814 First = 0;
815 }
816 if (! First)
817 {
818 Output(Out, ";\n");
819 }
820 Output(Out, "char *DestBase;\n");
821 Output(Out, "PULONG DestPtr;\n");
822 if (RopInfo->UsesSource)
823 {
824 Output(Out, "char *SourceBase;\n");
825 Output(Out, "PULONG SourcePtr;\n");
826 Output(Out, "ULONG RawSource;\n");
827 Output(Out, "unsigned SourcePixels, BaseSourcePixels;\n");
828 }
829 if (32 == Bpp)
830 {
831 Output(Out, "ULONG CenterCount;\n");
832 }
833 else
834 {
835 Output(Out, "ULONG LeftCount, CenterCount, RightCount;\n");
836 }
837 if (ROPCODE_GENERIC == RopInfo->RopCode)
838 {
839 Output(Out, "BOOLEAN UsesDest, UsesSource, UsesPattern;\n");
840 Output(Out, "\n");
841 Output(Out, "UsesDest = ROP4_USES_DEST(BltInfo->Rop4);\n");
842 Output(Out, "UsesSource = ROP4_USES_SOURCE(BltInfo->Rop4);\n");
843 Output(Out, "UsesPattern = ROP4_USES_PATTERN(BltInfo->Rop4);\n");
844 }
845 Output(Out, "\n");
846 if (! RopInfo->UsesSource)
847 {
848 CreateBase(Out, 0, 0, Bpp);
849 CreateCounts(Out, Bpp);
850 MARK(Out);
851 }
852 Output(Out, "LineCount = BltInfo->DestRect.bottom - BltInfo->DestRect.top;\n");
853
854 Output(Out, "\n");
855 if (RopInfo->UsesPattern)
856 {
857 if (ROPCODE_GENERIC == RopInfo->RopCode)
858 {
859 Output(Out, "if (UsesPattern && NULL != BltInfo->PatternSurface)\n");
860 }
861 else
862 {
863 Output(Out, "if (NULL != BltInfo->PatternSurface)\n");
864 }
865 Output(Out, "{\n");
866 CreateActionBlock(Out, Bpp, RopInfo, FLAG_PATTERNSURFACE);
867 MARK(Out);
868 Output(Out, "}\n");
869 Output(Out, "else\n");
870 Output(Out, "{\n");
871 if (ROPCODE_GENERIC == RopInfo->RopCode)
872 {
873 Output(Out, "if (UsesPattern)\n");
874 Output(Out, "{\n");
875 }
876 for (Partial = 0; Partial < 32 / Bpp; Partial++)
877 {
878 if (0 == Partial)
879 {
880 Output(Out, "Pattern = BltInfo->Brush->iSolidColor");
881 }
882 else
883 {
884 Output(Out, " (BltInfo->Brush->iSolidColor << %d)",
885 Partial * Bpp);
886 }
887 if (32 / Bpp <= Partial + 1)
888 {
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 \"w32k.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 for (Index = 0; Index < sizeof(DestBpp) / sizeof(DestBpp[0]); Index++)
1029 {
1030 Generate(argv[1], DestBpp[Index]);
1031 }
1032
1033 return 0;
1034 }