[ros-dev] DIB code generator
Robert Köpferl
rob at koepferl.de
Fri Jun 10 22:18:53 CEST 2005
I think, this size increase is not worth it. If you say win32k will
triple in size, that's 200% plus. And just for ROP and so on which is
just sparely used. I think of one generic method that is capable of
doing all BitBlt modes and a hand full generated/hand mande routines
wich do the usual stuff as invert and 1:1
Ge van Geldorp wrote:
> One of the things which has bothered me a bit is the code duplication we
> have in our DIB engine (subsys/win32k/dib). Most of the BitBlt routines in
> there are very similar. With the recent interest in optimizations a bunch of
> new (almost identical) routines were added. Don't get me wrong, I'm not
> saying that adding those optimizations was a bad idea, I'm just pointing out
> that we have a lot of code duplication.
>
> There are 256 possible ROP codes, we support 1bpp, 4bpp, 8bpp, 16bpp, 24bpp
> and 32bpp, so in theory there could be 1536 routines with basically the same
> structure. I've been playing around with the idea to write a code generator
> which would generate the source code for those routines. That would cut down
> on the duplicated source code and associated maintenance problems (you only
> need to change the code generator) while still allowing optimized code for
> each individual ROP code.
>
> Just to give you an idea what such a code generator would look like, I've
> attached my first attempt. Please note that it doesn't really try to
> optimize the generated code yet, it's just to give an impression. The code
> generated (16bpp only atm) is rather large, you can get it from
> ftp://ftp.geldorp.nl/pub/ReactOS/dib16gen.c if you like (or compile the code
> generator ("gcc -o gendib gendib.c") and run it).
>
> A possible problem is that the generated code is quite large. When using the
> generated 16bpp code, size of win32k.sys increases by about 350kb.
> Extrapolating this for all bpps, it would mean that win32k.sys would triple
> in size.
>
> So, I'm wondering what you guys are thinking. Should we basically trade
> memory for speed? Problem is that I can't quantify the speed increase at the
> moment.
>
> Gé van Geldorp.
>
>
> ------------------------------------------------------------------------
>
> #include <stdio.h>
>
> #define USES_DEST(RopCode) ((((RopCode) & 0xaa) >> 1) != ((RopCode) & 0x55))
> #define USES_SOURCE(RopCode) ((((RopCode) & 0xcc) >> 2) != ((RopCode) & 0x33))
> #define USES_PATTERN(RopCode) ((((RopCode) & 0xf0) >> 4) != ((RopCode) & 0x0f))
>
> static void
> PrintRoutineName(FILE *Out, unsigned Bpp, unsigned RopCode)
> {
> static struct
> {
> unsigned RopCode;
> char *Name;
> }
> KnownCodes[] =
> {
> { 0x00, "BLACKNESS" },
> { 0x11, "NOTSRCERASE" },
> { 0x33, "NOTSRCCOPY" },
> { 0x44, "SRCERASE" },
> { 0x55, "DSTINVERT" },
> { 0x5a, "PATINVERT" },
> { 0x66, "SRCINVERT" },
> { 0x88, "SRCAND" },
> { 0xbb, "MERGEPAINT" },
> { 0xc0, "MERGECOPY" },
> { 0xcc, "SRCCOPY" },
> { 0xee, "SRCPAINT" },
> { 0xf0, "PATCOPY" },
> { 0xfb, "PATPAINT" },
> { 0xff, "WHITENESS" }
> };
> unsigned Index;
>
> for (Index = 0; Index < sizeof(KnownCodes) / sizeof(KnownCodes[0]); Index++)
> {
> if (RopCode == KnownCodes[Index].RopCode)
> {
> fprintf(Out, "DIB_%uBPP_BitBlt_%s", Bpp, KnownCodes[Index].Name);
> return;
> }
> }
> fprintf(Out, "DIB_%uBPP_BitBlt_%02x", Bpp, RopCode);
> }
>
> static void
> CreatePrimitive(FILE *Out, unsigned Bpp, unsigned RopCode)
> {
> int UsesSource;
> int UsesPattern;
> int UsesDest;
>
> UsesSource = USES_SOURCE(RopCode);
> UsesPattern = USES_PATTERN(RopCode);
> UsesDest = USES_DEST(RopCode);
>
> fprintf(Out, "\n");
> fprintf(Out, "static void\n");
> PrintRoutineName(Out, Bpp, RopCode);
> fprintf(Out, "(PBLTINFO BltInfo)\n");
> fprintf(Out, "{\n");
> fprintf(Out, " ULONG DestX, DestY;\n");
> if (UsesSource)
> {
> fprintf(Out, " ULONG SourceX, SourceY;\n");
> }
> if (UsesPattern)
> {
> fprintf(Out, " ULONG PatternY = 0;\n");
> }
> fprintf(Out, " ULONG Dest = 0, Source = 0, Pattern = 0;\n");
> fprintf(Out, " PULONG DestBits;\n");
> fprintf(Out, " ULONG RoundedRight;\n");
> fprintf(Out, "\n");
> fprintf(Out, " RoundedRight = BltInfo->DestRect.right -\n");
> fprintf(Out, " ((BltInfo->DestRect.right - BltInfo->DestRect.left) & 0x1);\n");
> if (UsesSource)
> {
> fprintf(Out, " SourceY = BltInfo->SourcePoint.y;\n");
> }
> fprintf(Out, " DestBits = (PULONG)(\n");
> fprintf(Out, " BltInfo->DestSurface->pvScan0 +\n");
> fprintf(Out, " (BltInfo->DestRect.left << 1) +\n");
> fprintf(Out, " BltInfo->DestRect.top * BltInfo->DestSurface->lDelta);\n");
> fprintf(Out, "\n");
> if (UsesPattern)
> {
> fprintf(Out, " if (BltInfo->PatternSurface)\n");
> fprintf(Out, " {\n");
> fprintf(Out, " PatternY = (BltInfo->DestRect.top + BltInfo->BrushOrigin.y) %\n");
> fprintf(Out, " BltInfo->PatternSurface->sizlBitmap.cy;\n");
> fprintf(Out, " }\n");
> fprintf(Out, " else\n");
> fprintf(Out, " {\n");
> fprintf(Out, " Pattern = BltInfo->Brush->iSolidColor |\n");
> fprintf(Out, " (BltInfo->Brush->iSolidColor << 16);\n");
> fprintf(Out, " }\n");
> }
> fprintf(Out, "\n");
> fprintf(Out, " for (DestY = BltInfo->DestRect.top; DestY < BltInfo->DestRect.bottom; DestY++)\n");
> fprintf(Out, " {\n");
> if (UsesSource)
> {
> fprintf(Out, " SourceX = BltInfo->SourcePoint.x;\n");
> fprintf(Out, "\n");
> }
> fprintf(Out, " for (DestX = BltInfo->DestRect.left; DestX < RoundedRight; DestX += 2, DestBits++");
> if (UsesSource)
> {
> fprintf(Out, ", SourceX += 2");
> }
> fprintf(Out, ")\n");
> fprintf(Out, " {\n");
> if (UsesDest)
> {
> fprintf(Out, " Dest = *DestBits;\n");
> fprintf(Out, "\n");
> }
> if (UsesSource)
> {
> fprintf(Out, " Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);\n");
> fprintf(Out, " Source |= DIB_GetSource(BltInfo->SourceSurface, SourceX + 1, SourceY, BltInfo->XlateSourceToDest) << 16;\n");
> fprintf(Out, "\n");
> }
> if (UsesPattern)
> {
> fprintf(Out, " if (BltInfo->PatternSurface)\n");
> fprintf(Out, " {\n");
> fprintf(Out, " Pattern = DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest);\n");
> fprintf(Out, " Pattern |= DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x + 1) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest) << 16;\n");
> fprintf(Out, " }\n");
> fprintf(Out, "\n");
> }
> fprintf(Out, " *DestBits = DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern);\n");
> fprintf(Out, " }\n");
> fprintf(Out, "\n");
> fprintf(Out, " if (DestX < BltInfo->DestRect.right)\n");
> fprintf(Out, " {\n");
> if (UsesDest)
> {
> fprintf(Out, " Dest = *((PUSHORT)DestBits);\n");
> fprintf(Out, "\n");
> }
> if (UsesSource)
> {
> fprintf(Out, " Source = DIB_GetSource(BltInfo->SourceSurface, SourceX, SourceY, BltInfo->XlateSourceToDest);\n");
> }
> if (UsesPattern)
> {
> fprintf(Out, " if (BltInfo->PatternSurface)\n");
> fprintf(Out, " {\n");
> fprintf(Out, " Pattern = DIB_GetSource(BltInfo->PatternSurface, (DestX + BltInfo->BrushOrigin.x) % BltInfo->PatternSurface->sizlBitmap.cx, PatternY, BltInfo->XlatePatternToDest);\n");
> fprintf(Out, " }\n");
> fprintf(Out, "\n");
> }
> fprintf(Out, " DIB_16BPP_PutPixel(BltInfo->DestSurface, DestX, DestY, DIB_DoRop(BltInfo->Rop4, Dest, Source, Pattern) & 0xFFFF);\n");
> fprintf(Out, " DestBits = (PULONG)((ULONG_PTR)DestBits + 2);\n");
> fprintf(Out, " }\n");
> fprintf(Out, "\n");
> if (UsesSource)
> {
> fprintf(Out, " SourceY++;\n");
> }
> if (UsesPattern)
> {
> fprintf(Out, " if (BltInfo->PatternSurface)\n");
> fprintf(Out, " {\n");
> fprintf(Out, " PatternY++;\n");
> fprintf(Out, " PatternY %= BltInfo->PatternSurface->sizlBitmap.cy;\n");
> fprintf(Out, " }\n");
> }
> fprintf(Out, " DestBits = (PULONG)(\n");
> fprintf(Out, " (ULONG_PTR)DestBits -\n");
> fprintf(Out, " ((BltInfo->DestRect.right - BltInfo->DestRect.left) << 1) +\n");
> fprintf(Out, " BltInfo->DestSurface->lDelta);\n");
> fprintf(Out, " }\n");
> fprintf(Out, "}\n");
> }
>
> static void
> CreateTable(FILE *Out, unsigned Bpp)
> {
> unsigned RopCode;
>
> fprintf(Out, "\n");
> fprintf(Out, "static void (*PrimitivesTable[256])(PBLTINFO) =\n");
> fprintf(Out, " {\n");
> for (RopCode = 0; RopCode < 256; RopCode++)
> {
> fprintf(Out, " ");
> PrintRoutineName(Out, Bpp, RopCode);
> if (RopCode < 255)
> {
> putc(',', Out);
> }
> putc('\n', Out);
> }
> fprintf(Out, " };\n");
> }
>
> static void
> CreateBitBlt(FILE *Out, unsigned Bpp)
> {
> fprintf(Out, "\n");
> fprintf(Out, "BOOLEAN\n");
> fprintf(Out, "DIB_%uBPP_BitBlt(PBLTINFO BltInfo)\n", Bpp);
> fprintf(Out, "{\n");
> fprintf(Out, " PrimitivesTable[BltInfo->Rop4 & 0xff](BltInfo);\n");
> fprintf(Out, "\n");
> fprintf(Out, " return TRUE;\n");
> fprintf(Out, "}\n");
> }
>
> int
> main(int argc, char *argv[])
> {
> FILE *Out;
> unsigned RopCode;
> unsigned Bpp;
>
> Bpp = 16;
> Out = fopen("dib16gen.c", "w");
> if (NULL == Out)
> {
> perror("Error opening output file");
> exit(1);
> }
>
> fprintf(Out, "/* This is a generated file. Please do not edit */\n");
> fprintf(Out, "\n");
> fprintf(Out, "#include \"w32k.h\"\n");
>
> for (RopCode = 0; RopCode < 256; RopCode++)
> {
> CreatePrimitive(Out, Bpp, RopCode);
> }
> CreateTable(Out, Bpp);
> CreateBitBlt(Out, Bpp);
>
> fclose(Out);
>
> return 0;
> }
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Ros-dev mailing list
> Ros-dev at reactos.com
> http://reactos.com:8080/mailman/listinfo/ros-dev
More information about the Ros-dev
mailing list