Author |
Topic: Bitmap clipper & plotter (BASIC prototypes) (Read 1240 times) |
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Bitmap clipper & plotter (BASIC prototypes)
« Reply #4 on: Mar 5th, 2012, 03:18am » |
|
Here is a speed test comparing DrawIconRTR and GFXLIB_PlotScaleBlend.
The two routines, admittedly, do slightly different things:
DrawIconRTR alphablends on a pixel-by-pixel basis (using the alpha value of each source bitmap pixel, and pre-multiplied alphas of background pixels).
GFXLIB_PlotScaleBlend uses a single, global alpha (or opacity) value for all pixels, and doesn't read background alphas.
So the two routines do quite similar things.
GFXLIB_PlotScaleBlend doesn't make use of any MMX/SIMD instructions.
DrawIconRTR is certainly faster until larger scale factors are specified, and much clipping needs to be done. Eventually, GFXLIB_PlotScaleBlend overtakes. I think I know why this is, but it's currently 4:12 AM and I'm too tired to explain my thoughts.
GFXLIB is required to run the source code below.
Here's a link to the EXE (+ .BBC source):
http://www.bb4wgames.com/temp/plotspeedtest.zip
Code:
REM. -----------------
REM. PlotSpeedTest.BBC
REM. -----------------
REM.
REM. Compare -- not too scientifically! -- plotting speeds of
REM. DrawIconRTR and GFXLIB_PlotScaleBlend
MODE 8
SOUND 1, 0, 0, 0 : SOUND OFF
ON ERROR OSCLI "REFRESH ON" : ON : CLS : REPORT : PRINT " at line "; ERL : VDU 7 : END
INSTALL @lib$ + "GFXLIB2.BBC" : PROCInitGFXLIB(d{}, 0)
INSTALL @lib$ + "GFXLIB_modules\PlotScaleBlend.BBC" : PROCInitModule
GetTickCount% = FNSYS_NameToAddress( "GetTickCount" )
DIM mc% 255
OSCLI "LOAD """ + @lib$ + "DrawIconRTR.bin"" " + STR$~mc%
DrawIconRTR% = mc% + 3
DIM Buffer{T%,W%,H%,B%,P%,M%}
Buffer.W% = @vdu%!208 : Buffer.H% = @vdu%!212 : Buffer.M% = d.bmBuffAddr%
REM. Create a 'test' 128x80, 32-bpp ARGB bitmap
bmW% = 128 : bmH% = 80 : bm% = FN_createTestBitmap( bmW%, bmH% )
DIM Bitmap{T%,W%,H%,B%,P%,M%}
Bitmap.W% = bmW% : Bitmap.H% = bmH% : Bitmap.M% = bm%
COLOUR 15 : PRINT '" DrawIconRTR vs. GFXLIB_PlotScaleBlend"' : COLOUR 7
INPUT '" Enter a scale factor (1.0) "; scale
INPUT '" How many iterations? (10000) "; N%
IF N% <= 0 THEN N% = 10000
IF scale = 0 THEN scale = 1.0
IF scale < 0 THEN scale *= -1.0
DIM pt{X%,Y%}
dx% = bmW%*scale
dy% = bmH%*scale
pt.X% = 320
pt.Y% = 256
bmW2% = scale * bmW%
bmH2% = scale * bmH%
OFF : WAIT 50
SYS "GetCurrentProcess" TO hprocess%
SYS "SetPriorityClass", hprocess%, &80
REM. Display the 'test bitmap' using DrawIconRTR
SYS DrawIconRTR%, Buffer{}, pt.X%, pt.Y%, Bitmap{}, dx%, dy%
SYS "InvalidateRect", @hwnd%, 0, 0
*REFRESH
REM. Time DrawIconRTR%
PRINT '" Timing DrawIconRTR ("; N%; " calls; scale factor: ";scale;")..." : WAIT 50
*REFRESH OFF
SYS GetTickCount% TO timeA_0%
FOR I% = 1 TO N%
SYS DrawIconRTR%, Buffer{}, pt.X%, pt.Y%, Bitmap{}, dx%, dy%
NEXT
SYS GetTickCount% TO timeA_1%
*REFRESH ON
REM. Display the 'test bitmap' using GFXLIB_PlotScaleBlend
SYS GFXLIB_PlotScaleBlend%, d{}, bm%, bmW%, bmH%, bmW2%, bmH2%, pt.X%, pt.Y%, 254
SYS "InvalidateRect", @hwnd%, 0, 0
*REFRESH
REM. Time GFXLIB_PlotScaleBlend
PRINT '" Timing GFXLIB_PlotScaleBlend ("; N%; " calls; scale factor: ";scale;")..." : WAIT 50
*REFRESH OFF
SYS GetTickCount% TO timeB_0%
FOR I% = 1 TO N%
SYS GFXLIB_PlotScaleBlend%, d{}, bm%, bmW%, bmH%, bmW2%, bmH2%, pt.X%, pt.Y%, 254
NEXT
SYS GetTickCount% TO timeB_1%
*REFRESH ON
SYS "GetCurrentProcess" TO hprocess%
SYS "SetPriorityClass", hprocess%, &20
PRINT '" " + STRING$(40,"-")'
PRINT '" DrawIconRTR took "; (timeA_1% - timeA_0%)/1000; " s."
PRINT '" GFXLIB_PlotScaleBlend took "; (timeB_1% - timeB_0%)/1000; " s."
COLOUR 3 : PRINT ''" Finished." : COLOUR 7
SOUND 1, -10, 220, 1
ON
END
DEF FN_createTestBitmap( bmW%, bmH% )
LOCAL bm%, I%, X%, Y%, r%
DIM bm% 4 * bmW%*bmH% +3 : REM. Needs extra 4 bytes (not 3!) for memory alignment
bm% = (bm% + 3) AND -4 : REM. Ensures bitmap base address is DWORD-aligned (divisible by 4)
REM. Fill our bitmap with the colour "SlateBlue" (= &6A5ACD)
FOR I% = bm% TO bm% + (4*bmW%*bmH% - 1) STEP 4
!I% = &6A5ACD
NEXT I%
REM. Give our bitmap a bright yellow border
FOR X% = 0 TO bmW%-1
bm%!(4*X%) = &FFFF00
bm%!(4*(bmW%*(bmH%-1) + X%)) = &FFFF00
NEXT X%
FOR Y% = 0 TO bmH%-1
bm%!(4*Y%*bmW%) = &FFFF00
bm%!(4*(Y%*bmW% + (bmW%-1))) = &FFFF00
NEXT Y%
REM. Draw a sine wave on the bitmap
FOR X% = 0 TO bmW%-1
Y% = bmH%DIV2 + bmH%DIV4*SIN(4*PI * X%/(bmW%-1))
bm%!(4*(Y%*bmW% + X%)) = &FFFFFF
NEXT X%
REM. Draw a circle on our bitmap
FOR I% = 0 TO 359
r% = 0.25 * SQR((bmW%/2)^2 + (bmH%/2)^2)
X% = bmW%/2 + r%*SINRADI%
Y% = bmH%/2 + r%*COSRADI%
IF X% < 0 X% = 0
IF Y% < 0 Y% = 0
IF X% > bmW%-1 X% = bmW%-1
IF Y% > bmH%-1 Y% = bmH%-1
bm%!(4*(Y%*bmW% + X%)) = &00FF00
NEXT I%
= bm%
David.
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Bitmap clipper & plotter (BASIC prototypes)
« Reply #5 on: Mar 5th, 2012, 4:44pm » |
|
on Mar 5th, 2012, 03:18am, David Williams wrote:| DrawIconRTR alphablends on a pixel-by-pixel basis (using the alpha value of each source bitmap pixel, and pre-multiplied alphas of background pixels). |
|
I don't really know what you mean by "pre-multiplied alphas of background pixels" here. In what sense do 'background' pixels have an alpha anyway? I don't guarantee that my routine will do anything sensible with the 'alpha' byte in the background bitmap: it may well corrupt it. I treat it as a 'don't care' byte.
Quote:| So the two routines do quite similar things |
|
Does yours have the 'reflect' (about either axis) option? That added a significant degree of complexity, as I recollect.
My routine is, of course, optimised for no clipping, since (at least in my applications) clipping is very much an exceptional case.
Richard.
|
| « Last Edit: Mar 5th, 2012, 4:54pm by admin » |
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Bitmap clipper & plotter (BASIC prototypes)
« Reply #6 on: Mar 6th, 2012, 03:21am » |
|
on Mar 5th, 2012, 4:44pm, Richard Russell wrote:| I don't really know what you mean by "pre-multiplied alphas of background pixels" here. |
|
Neither do I (lol).
I now know that what I wrote was nonsense.
on Mar 5th, 2012, 4:44pm, Richard Russell wrote:| Does yours have the 'reflect' (about either axis) option? That added a significant degree of complexity, as I recollect. |
|
No, mine doesn't.
The only GFXLIB routine that performs any kind of flipping/reflection is GFXLIB_PlotFlip (and a variant of it). This may be about to change, however.
David.
|
|
Logged
|
|
|
|
|