From 74c2cde32c76549e802aa6e17a60466b86d88303 Mon Sep 17 00:00:00 2001 From: ketmar Date: Wed, 1 Dec 2021 08:43:38 +0000 Subject: [PATCH] egra: some cleanups in agg mini rasterizer FossilOrigin-Name: 7742935b78eddfc7b42870b1140c8cf1fa2df41a46d6718e643abdedfa180a0d --- egra/gfx/aggmini/render.d | 233 ++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 152 deletions(-) diff --git a/egra/gfx/aggmini/render.d b/egra/gfx/aggmini/render.d index fc06458..0f6e786 100644 --- a/egra/gfx/aggmini/render.d +++ b/egra/gfx/aggmini/render.d @@ -58,10 +58,6 @@ import iv.egra.gfx.lowlevel; align(1) struct Cell { align(1): public: - //static uint packCoord (in int x, in int y) pure nothrow @safe @nogc { pragma(inline, true); return (y<<16)|(x&0xffff); } - -public: - //uint packedCoord; short x, y; int cover; int area; @@ -72,42 +68,31 @@ public: public nothrow @trusted @nogc: this (in int cx, in int cy, in int c, in int a) pure { pragma(inline, true); - //packedCoord = packCoord(cx, cy); - x = cast(short)cx; y = cast(short)cy; + x = cast(short)cx; + y = cast(short)cy; cover = c; area = a; } bool isEqual (in int cx, in int cy) pure const { pragma(inline, true); - //return (x == cx && y == cy); return (((cast(short)cx)^x)|((cast(short)cy)^y)) == 0; } - //uint getPackedCoord () const pure nothrow @safe @nogc { pragma(inline, true); return (cast(uint)y<<16)|(cast(uint)cast(ushort)x); } - uint getPackedCoord () const pure nothrow @trusted @nogc { pragma(inline, true); return *(cast(const uint*)&x); } + uint getPackedCoord () const pure { pragma(inline, true); return *(cast(const uint*)&x); } - bool isLessThan (in ref Cell other) const pure nothrow @trusted @nogc { + bool isLessThan (in ref Cell other) const pure { pragma(inline, true); return (y < other.y || (y == other.y && x < other.x)); } - //@property int x () const pure { pragma(inline, true); return cast(int)cast(short)(packedCoord&0xffff); } - //@property int y () const pure { pragma(inline, true); return cast(int)cast(short)(packedCoord>>16); } - void setCover (in int c, in int a) { pragma(inline, true); cover = c; area = a; } void addCover (in int c, in int a) { pragma(inline, true); cover += c; area += a; } - void setCoord (in int cx, in int cy) { - pragma(inline, true); - //packedCoord = packCoord(cx, cy); - x = cast(short)cx; y = cast(short)cy; - } - void set (in int cx, in int cy, in int c, in int a) { pragma(inline, true); - //packedCoord = packCoord(cx, cy); - x = cast(short)cx; y = cast(short)cy; + x = cast(short)cx; + y = cast(short)cy; cover = c; area = a; } @@ -115,9 +100,8 @@ public nothrow @trusted @nogc: // ////////////////////////////////////////////////////////////////////////// // -/* An internal class that implements the main rasterization algorithm. - Used in the rasterizer. Should not be used direcly. -*/ +// an internal class that implements the main rasterization algorithm. +// used in the rasterizer. should not be used direcly. struct Outline { private nothrow @trusted @nogc: enum : uint { @@ -169,7 +153,6 @@ private: auto cc = cast(Cell*)realloc(null, Cell.sizeof*CellBlockSize); if (cc is null) assert(0, "out of memory"); memset(cc, 0, Cell.sizeof*CellBlockSize); - //foreach (ref c; cc[0..CellBlockSize]) c = Cell.init; mCells[mNumBlocks++] = cc; } mCurCellPtr = mCells[mCurBlock++]; @@ -192,15 +175,12 @@ public: } void reset () { - mNumCells = 0; - mCurBlock = 0; + mNumCells = mCurBlock = 0; mCurCell.set(0x7fff, 0x7fff, 0, 0); mFlags |= SortRequired; mFlags &= ~NotClosed; - mMinX = 0x7fffffff; - mMinY = 0x7fffffff; - mMaxX = -0x7fffffff; - mMaxY = -0x7fffffff; + mMinX = mMinY = +0x7fffffff; + mMaxX = mMaxY = -0x7fffffff; } void moveTo (in int x, in int y) { @@ -233,10 +213,10 @@ public: @property float currX () const pure { pragma(inline, true); return cast(float)mCurX/cast(float)PolyBaseSize; } @property float currY () const pure { pragma(inline, true); return cast(float)mCurY/cast(float)PolyBaseSize; } - @property int minX () const pure { pragma(inline, true); return mMinX; } - @property int minY () const pure { pragma(inline, true); return mMinY; } - @property int maxX () const pure { pragma(inline, true); return mMaxX; } - @property int maxY () const pure { pragma(inline, true); return mMaxY; } + @property int minX () const pure { pragma(inline, true); return (mMinX <= mMaxX ? mMinX : 0); } + @property int minY () const pure { pragma(inline, true); return (mMinY <= mMaxY ? mMinY : 0); } + @property int maxX () const pure { pragma(inline, true); return (mMinX <= mMaxX ? mMaxX : 0); } + @property int maxY () const pure { pragma(inline, true); return (mMinY <= mMaxY ? mMaxY : 0); } @property uint numCells () const pure { pragma(inline, true); return mNumCells; } @@ -360,9 +340,6 @@ private: int dx = x2-x1; int dy = y2-y1; - //int xFrom, xTo; - //int p, rem, mod, lift, delta, first, incr; - // vertical line: we have to calculate start and end cells, // and then the common values of the area and coverage for // all cells of the line. we know exactly there's only one @@ -388,12 +365,12 @@ private: delta = first+first-PolyBaseSize; area = twoFx*delta; while (ey1 != ey2) { - //renderScanLine(ey1, xFrom, PolyBaseSize - first, xFrom, first); + //renderScanLine(ey1, xFrom, PolyBaseSize-first, xFrom, first); mCurCell.setCover(delta, area); ey1 += incr; setCurCell(ex, ey1); } - //renderScanLine(ey1, xFrom, PolyBaseSize - first, xFrom, fy2); + //renderScanLine(ey1, xFrom, PolyBaseSize-first, xFrom, fy2); delta = fy2-PolyBaseSize+first; mCurCell.addCover(delta, twoFx*delta); return; @@ -448,24 +425,6 @@ private: private: static void qsortCells (Cell** start, uint num) { - /* - static void swapCells (Cell** a, Cell** b) nothrow @trusted @nogc { - pragma(inline, true); - auto temp = *a; - *a = *b; - *b = temp; - } - - static bool lessThan (in Cell** a, in Cell** b) pure nothrow @trusted @nogc { - pragma(inline, true); - version(none) { - return ((**a).packedCoord < (**b).packedCoord); - } else { - return (*a).isLessThan(**b); - } - } - */ - // two macros static enum swapCellsMixin(string a, string b) = ` { auto temp_ = *(`~a~`); @@ -650,8 +609,6 @@ struct ScanLine { private: int mMinX; uint mMaxLen; - int mDX; - int mDY; int mLastX = 0x7fff; int mLastY = 0x7fff; ubyte* mCovers; @@ -662,8 +619,6 @@ private: ushort* mCurCount; public: - enum AAShift = 8; - static struct Iterator { private: const(ubyte)* mCovers; @@ -703,7 +658,7 @@ public nothrow @trusted @nogc: auto iterator () const pure { pragma(inline, true); return Iterator(this); } - void reset (int minX, int maxX, int dx=0, int dy=0) { + void reset (int minX, int maxX) { uint maxLen = maxX-minX+2; if (maxLen > mMaxLen) { import core.stdc.stdlib : realloc; @@ -715,8 +670,6 @@ public nothrow @trusted @nogc: if (mCounts is null) assert(0, "out of memory"); mMaxLen = maxLen; } - mDX = dx; - mDY = dy; mLastX = 0x7fff; mLastY = 0x7fff; mMinX = minX; @@ -764,53 +717,13 @@ public nothrow @trusted @nogc: } @property bool isReady (int y) const pure { pragma(inline, true); return (mNumSpans && (y^mLastY)); } - @property int baseX () const pure { pragma(inline, true); return mMinX+mDX; } - @property int y () const pure { pragma(inline, true); return mLastY+mDY; } + @property int baseX () const pure { pragma(inline, true); return mMinX; } + @property int y () const pure { pragma(inline, true); return mLastY; } @property uint spanCount () const pure { pragma(inline, true); return mNumSpans; } } // ////////////////////////////////////////////////////////////////////////// // -/* This class template is used basically for rendering scanlines. - Usage: - auto ras = Rasterizer(); - - // Making polygon - // ras.moveTo(...); - // ras.lineTo(...); - // ... - - // Rendering - ras.render(ren, Color(255, 127, 0)); -*/ -public struct Renderer { -public nothrow @trusted @nogc: - mixin(DisableCopyingMixin); - - static void render (in ref ScanLine sl, in GxColor clr, in ref GxRect clipRect) { - if (clipRect.size.h < 1 || clipRect.size.w < 1 || sl.y < clipRect.pos.y || sl.y >= clipRect.pos.y+clipRect.size.h) return; - immutable GxColorU c = GxColorU(clr); - uint spanCount = sl.spanCount; - immutable int baseX = sl.baseX; - uint* row = vglTexBuf+cast(uint)sl.y*cast(uint)VBufWidth; - auto span = sl.iterator; - //{ import core.stdc.stdio : stderr, fprintf; fprintf(stderr, "***RENDER: y=%d; spanCount=%u; baseX=%d\n", sl.y, spanCount, baseX); } - do { - int x = span.next+baseX; - int pixelCount = span.pixelCount; - int leftSkip = void; - //{ import core.stdc.stdio : stderr, fprintf; fprintf(stderr, " y=%d; x=%d; pixelCount=%d\n", sl.y, x, pixelCount); } - if (clipRect.clipHStripe(ref x, sl.y, ref pixelCount, &leftSkip)) { - //{ import core.stdc.stdio : stderr, fprintf; fprintf(stderr, " y=%d; x=%d; pixelCount=%d; leftSkip=%d\n", sl.y, x, pixelCount, leftSkip); } - const(ubyte)* covers = span.covers+leftSkip; - memBlendColorCoverage(row+x, covers, clr, pixelCount); - } - } while (--spanCount); - } -} - - -// ////////////////////////////////////////////////////////////////////////// // /* These constants determine the subpixel accuracy, to be more precise, the number of bits of the fractional part of the coordinates. The possible coordinate capacity in bits can be calculated by formula: @@ -824,10 +737,10 @@ enum : uint { } -int polyCoord (in float c) pure nothrow @safe @nogc { pragma(inline, true); return (cast(int)(c*(PolyBaseSize*2))+1)/2; } +int polyCoord (in float c) pure nothrow @safe @nogc { pragma(inline, true); return (cast(int)(c*(PolyBaseSize*2.0f))+1)/2; } -int dbl2fix (in float c) pure nothrow @safe @nogc { pragma(inline, true); return cast(int)(c*PolyBaseSize); } -float fix2dbl (in int c) pure nothrow @safe @nogc { pragma(inline, true); return cast(float)c/cast(float)PolyBaseSize; } +//int dbl2fix (in float c) pure nothrow @safe @nogc { pragma(inline, true); return cast(int)(c*PolyBaseSize); } +//float fix2dbl (in int c) pure nothrow @safe @nogc { pragma(inline, true); return cast(float)c/cast(float)PolyBaseSize; } // ////////////////////////////////////////////////////////////////////////// // @@ -860,11 +773,11 @@ float fix2dbl (in int c) pure nothrow @safe @nogc { pragma(inline, true); return */ public struct Rasterizer { public nothrow @trusted @nogc: - enum : uint { - AAShift = ScanLine.AAShift, + enum { + AAShift = 8, AANum = 1<>(PolyBaseShift*2+1-AAShift); + if (cover < 0) cover = -cover; + if (mFillingRule == FillRule.EvenOdd) { + cover &= AA2Mask; + if (cover > AANum) cover = AA2Num-cover; + } + if (cover > AAMask) cover = AAMask; + return cover; + } + +public: mixin(DisableCopyingMixin); void reset () { mOutline.reset(); } @property FillRule fillRule () const pure { pragma(inline, true); return mFillingRule; } - @property void fillRule (FillRule v) { pragma(inline, true); mFillingRule = v; } + @property void fillRule (in FillRule v) { pragma(inline, true); mFillingRule = v; } void gamma (in float g) { foreach (immutable uint i; 0..256) { @@ -918,40 +860,32 @@ public: @property int maxX () const pure { pragma(inline, true); return mOutline.maxX; } @property int maxY () const pure { pragma(inline, true); return mOutline.maxY; } - private uint calculateAlpha (in int area) const pure { - int cover = area>>(PolyBaseShift*2+1-AAShift); - if (cover < 0) cover = -cover; - if (mFillingRule == FillRule.EvenOdd) { - cover &= AA2Mask; - if (cover > AANum) cover = AA2Num-cover; - } - if (cover > AAMask) cover = AAMask; - return cover; - } - void render (in ref GxRect clipRect, in GxColor c, int dx=0, int dy=0) { - render(clipRect, c, AGGInvalidGradient(), dx, dy); + void render (in ref GxRect clipRect, in GxColor c) { + render(clipRect, c, AGGInvalidGradient()); } - void render(VG) (in ref GxRect clipRect, in GxColor c, in auto ref VG grad, int dx=0, int dy=0) - if (IsGoodVerticalGradient!VG) - { + void render(VG) (in ref GxRect clipRect, in GxColor c, in auto ref VG grad) if (IsGoodVerticalGradient!VG) { + if (clipRect.empty) return; + const(Cell)** cells = mOutline.cells(); if (mOutline.numCells() == 0) return; immutable bool useGrad = grad.isValid; void flushScanline () { - if (mScanline.y < clipRect.pos.y || mScanline.y > clipRect.y1) return; - if (!useGrad) { - // no gradient - Renderer.render(mScanline, c, clipRect); - } else { - Renderer.render(mScanline, grad.colorAtY(mScanline.y, c), clipRect); + if (mScanline.y >= clipRect.pos.y && mScanline.y <= clipRect.y1) { + if (!useGrad) { + // no gradient + renderSL(mScanline, c, clipRect); + } else { + renderSL(mScanline, grad.colorAtY(mScanline.y, c), clipRect); + } } + mScanline.resetSpans(); } - mScanline.reset(mOutline.minX, mOutline.maxX, dx, dy); + mScanline.reset(mOutline.minX, mOutline.maxX); int cover = 0; const(Cell)* curCell = *cells++; @@ -959,9 +893,9 @@ public: for (;;) { const(Cell)* startCell = curCell; - uint coord = curCell.getPackedCoord; int x = curCell.x; - int y = curCell.y; + immutable int y = curCell.y; + immutable uint coord = curCell.getPackedCoord; int area = startCell.area; cover += startCell.cover; @@ -974,12 +908,9 @@ public: } if (area) { - int alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area); + immutable int alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area); if (alpha) { - if (mScanline.isReady(y)) { - flushScanline(); - mScanline.resetSpans(); - } + if (mScanline.isReady(y)) flushScanline(); mScanline.addCell(x, y, mGamma.ptr[alpha]); } ++x; @@ -990,10 +921,7 @@ public: if (curCell.x > x) { int alpha = calculateAlpha(cover<<(PolyBaseShift+1)); if (alpha) { - if (mScanline.isReady(y)) { - flushScanline(); - mScanline.resetSpans(); - } + if (mScanline.isReady(y)) flushScanline(); mScanline.addSpan(x, y, curCell.x-x, mGamma.ptr[alpha]); } } @@ -1002,6 +930,7 @@ public: if (mScanline.spanCount) flushScanline(); } + // returns "gamma alpha" (0 means "no hit") ubyte hitTest (int tx, int ty) { const(Cell)** cells = mOutline.cells(); @@ -1013,9 +942,9 @@ public: for (;;) { const(Cell)* startCell = curCell; - uint coord = curCell.getPackedCoord; int x = curCell.x; - int y = curCell.y; + immutable int y = curCell.y; + immutable uint coord = curCell.getPackedCoord; if (y > ty) return false; @@ -1029,9 +958,9 @@ public: } if (area) { - immutable int alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area); - if (alpha && mGamma.ptr[alpha]) { - if (tx == x && ty == y) return mGamma.ptr[alpha]; + if (tx == x && ty == y) { + immutable int alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area); + if (alpha && mGamma.ptr[alpha]) return mGamma.ptr[alpha]; } ++x; } -- 2.11.4.GIT