## Efficient Drawing

New to FreeBASIC? Post your questions here.
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Efficient Drawing

The last rect is the the top most rect.

Code: Select all

`type scr    as integer w,h    as uinteger ptr pend typetype rect    as integer x,y,w,h    as ulong cend typesub init_rect(r as rect ptr,x as integer,y as integer,_              w as integer,h as integer,c as ulong)    r->x = x    r->y = y    r->w = w    r->h = h    r->c = cend subsub clear_scr(s as SCR ptr,c as ulong)    for i as integer = 0 to s->w * s->h -1        s->p[i] = c    next iend subsub draw_rect(s as SCR ptr,r as rect ptr)    dim as integer xx = r->x,yy = r->y,w = r->w,h = r->h        dim as uinteger ptr p = @s->p[yy*s->w +xx]    for y as integer = 0 to h  -1        for x as integer = 0 to w  -1            if p[x] shr 24 = 0 then               p[x] = r->c            end if        next x        p += s->w    next y    end subsub draw_rect1(s as SCR ptr,r as rect ptr)    dim as integer xx = r->x,yy = r->y,w = r->w,h = r->h        dim as uinteger ptr p = @s->p[yy*s->w +xx]    for y as integer = 0 to h  -1        for x as integer = 0 to w  -1            p[x] = r->c        next x        p += s->w    next y    end subdim as scr scsc.w = 800sc.h = 600screenres sc.w,sc.h,32sc.p = screenptr()dim as rect r(40)for i as integer = 1 to 40    init_rect(@r(i-1),i*10,i*10,300,180,rnd*&hff0000ff)next iclear_scr(@sc,&h0000007f)dim as double t = timer()screenlock()for i as integer = 0 to 39    draw_rect1(@sc,@r(i))next iscreenunlock()print using "##.####";timer()-tsleep 100t = timer()screenlock()for i as integer = 39 to 0 step -1    draw_rect(@sc,@r(i))next iscreenunlock()print using "##.####";timer()-tsleep`

Do you think this is enough?
Last edited by nimdays on Jan 03, 2018 4:53, edited 2 times in total.
paul doe
Posts: 549
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: Effecient Drawing

nimdays wrote:Do you think this is enough?

Um, I don't know. Enough for what? Btw, the code crashes on 64-bit; if you're accessing the pixel buffer directly, you should use ulongs (32-bit unsigned in both 32 and 64-bit) instead of uintegers, which are platform dependent (they are either 32 or 64 bits, depending on what compiler you use).
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Re: Effecient Drawing

paul doe wrote:
nimdays wrote:Do you think this is enough?

Um, I don't know. Enough for what? Btw, the code crashes on 64-bit; if you're accessing the pixel buffer directly, you should use ulongs (32-bit unsigned in both 32 and 64-bit) instead of uintegers, which are platform dependent (they are either 32 or 64 bits, depending on what compiler you use).

Thanks, I'll fix that.

The first is traditional way from the first rect and so on, And the second from the last rect first by checking the alpha channel of the destination.

Code: Select all

`if p[x] shr 24 = 0 then      p[x] = r->cend if`

By the way, I found this from pixman region source.
Maybe this is the most efficient ?

Code: Select all

` *  -----------                ----------- *  |         |                |         |          band 0 *  |         |  --------          -----------  -------- *  |         |  |      |  in y-x banded    |         |  |      |   band 1 *  |         |  |      |  form is       |         |  |      | *  -----------  |      |          -----------  -------- *               |      |             |      |   band 2 *               --------             --------`
paul doe
Posts: 549
Joined: Jul 25, 2017 17:22
Location: Argentina

### Re: Effecient Drawing

nimdays wrote:This is about overlapped rectangles.
The first is traditional way from the first rect and so on, And the second from the last rect first by checking the alpha channel of the destination.

Oh yeah, I see it now. Yes, it's an efficient approach. I use a very similar one here: https://www.freebasic.net/forum/viewtopic.php?f=15&t=26105. The only thing that you have to be careful, it's in using the pitch of a buffer, not its width. You can get the pitch of the screen via screenInfo() call, and of a buffer by casting a pixel buffer to a fb.image ptr:

Code: Select all

`screenInfo( , , , , sc.pitch ) '' <-- gets the pitch of the screencast( fb.image ptr, buffer )->pitch '' <-- gets the pitch of a pixel buffer`
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Re: Effecient Drawing

paul doe wrote:Oh yeah, I see it now. Yes, it's an efficient approach. I use a very similar one here: https://www.freebasic.net/forum/viewtopic.php?f=15&t=26105. The only thing that you have to be careful, it's in using the pitch of a buffer, not its width. You can get the pitch of the screen via screenInfo() call, and of a buffer by casting a pixel buffer to a fb.image ptr:

Code: Select all

`screenInfo( , , , , sc.pitch ) '' <-- gets the pitch of the screencast( fb.image ptr, buffer )->pitch '' <-- gets the pitch of a pixel buffer`

MrSwiss
Posts: 2679
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Efficient Drawing

This is now *portable*: compile's/run's with both compilers (32/64):

Code: Select all

`type scr    as integer   w, h    as ulong ptr p    Declare Sub _clear(As ULong)    ' NO variable-names required!end Typesub scr._clear(c as ulong)  ' embedded has always the type's info!    With This   ' scr type (direct, NO ptr's needed!)        for i as UInteger = 0 to .w * .h - 1            .p[i] = c        next    End Withend Sub' end scrtype rect    as integer  x, y, w, h    as ulong    c    Declare Sub init(As integer, as integer, as integer, as integer, as ULong)end typesub rect.init(x as integer, y as integer, _              w as integer, h as integer, _              c as ulong)    With This   ' rect type (direct, NO ptr's needed!)        .x = x : .y = y : .w = w : .h = h : .c = c    End Withend Sub' end rect' type independent subsub draw_rect(s as SCR ptr, r as rect ptr)    dim as integer  xx = r->x, yy = r->y, iw = r->w - 1, ih = r->h - 1    Dim As ULong    cc = r->c    dim as ulong ptr p = @s->p[yy * s->w + xx]    for j as UInteger = 0 to ih        for i As UInteger = 0 to iw            p[i] = cc        Next        p += s->w    NextEnd Sub' screen and (type) sc initdim as scr scWith sc    .w = 800 : .h = 600 ' type (width/height only)ScreenRes(.w, .h, 32)   ' screen (using type)    .p = screenptr()    ' type (screen access)End With' rectangle initdim as rect r(39)   ' = 40 elements!for i as UInteger = 0 to 39    r(i).init(i*10, i*10, 300, 180, Rnd*&hff0000ff) ' type embedded Sub (see below)next i' main startDim As Double   t1 = 0.0, t2 = 0.0, tssc._clear(&hFF00007F)  ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)ScreenLock()ts = Timer              ' timing 1 startFor i as UInteger = 0 to 39    draw_rect(@sc, @r(i))Nextt1 = Timer - ts         ' timing 1 endscreenunlock()print using "##.####"; t1Sleep(2500, 1)          ' wait 2.5 Sec.sc._clear(&hFF7F0000)   ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)screenlock()ts = timer()            ' timing 2 startFor i as integer = 39 to 0 step -1  ' the only one 'integer', because: 'down counting-loop'    draw_rect(@sc, @r(i))next it2 = Timer - ts         ' timing 2 endscreenunlock()print using "##.####"; t2Sleep' main end --- EOF ---`
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Re: Efficient Drawing

MrSwiss wrote:This is now *portable*: compile's/run's with both compilers (32/64):

Code: Select all

`type scr    as integer   w, h    as ulong ptr p    Declare Sub _clear(As ULong)    ' NO variable-names required!end Typesub scr._clear(c as ulong)  ' embedded has always the type's info!    With This   ' scr type (direct, NO ptr's needed!)        for i as UInteger = 0 to .w * .h - 1            .p[i] = c        next    End Withend Sub' end scrtype rect    as integer  x, y, w, h    as ulong    c    Declare Sub init(As integer, as integer, as integer, as integer, as ULong)end typesub rect.init(x as integer, y as integer, _              w as integer, h as integer, _              c as ulong)    With This   ' rect type (direct, NO ptr's needed!)        .x = x : .y = y : .w = w : .h = h : .c = c    End Withend Sub' end rect' type independent subsub draw_rect(s as SCR ptr, r as rect ptr)    dim as integer  xx = r->x, yy = r->y, iw = r->w - 1, ih = r->h - 1    Dim As ULong    cc = r->c    dim as ulong ptr p = @s->p[yy * s->w + xx]    for j as UInteger = 0 to ih        for i As UInteger = 0 to iw            p[i] = cc        Next        p += s->w    NextEnd Sub' screen and (type) sc initdim as scr scWith sc    .w = 800 : .h = 600 ' type (width/height only)ScreenRes(.w, .h, 32)   ' screen (using type)    .p = screenptr()    ' type (screen access)End With' rectangle initdim as rect r(39)   ' = 40 elements!for i as UInteger = 0 to 39    r(i).init(i*10, i*10, 300, 180, Rnd*&hff0000ff) ' type embedded Sub (see below)next i' main startDim As Double   t1 = 0.0, t2 = 0.0, tssc._clear(&hFF00007F)  ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)ScreenLock()ts = Timer              ' timing 1 startFor i as UInteger = 0 to 39    draw_rect(@sc, @r(i))Nextt1 = Timer - ts         ' timing 1 endscreenunlock()print using "##.####"; t1Sleep(2500, 1)          ' wait 2.5 Sec.sc._clear(&hFF7F0000)   ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)screenlock()ts = timer()            ' timing 2 startFor i as integer = 39 to 0 step -1  ' the only one 'integer', because: 'down counting-loop'    draw_rect(@sc, @r(i))next it2 = Timer - ts         ' timing 2 endscreenunlock()print using "##.####"; t2Sleep' main end --- EOF ---`

Thanks, I missed a lot.

By the way, You missed the alpha checker.
MrSwiss
Posts: 2679
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Efficient Drawing

nimdays wrote:By the way, You missed the alpha checker.
Nope, not missed, it didn't work, that's the reason, I've kicked it out ...

Btw: if you want to use transparency, you'll have to set ScreenRes(), accordingly:

Code: Select all

`ScreenRes(w, h, 32,, 64)    ' aka: GFX_ALPHA_PRIMITIVES = &h40, see: fbgfx.bi`

P.S. it doesn't make sense, to quote entire posts ... (you could easily remove the
whole code section).
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Re: Efficient Drawing

MrSwiss wrote:Btw: if you want to use transparency, you'll have to set ScreenRes(), accordingly:

Code: Select all

`ScreenRes(w, h, 32,, 64)    ' aka: GFX_ALPHA_PRIMITIVES = &h40, see: fbgfx.bi`

This is not about transparency, The second method will avoid drawing the area of the previous rectangles.
MrSwiss
Posts: 2679
Joined: Jun 02, 2013 9:27
Location: Switzerland

### Re: Efficient Drawing

nimdays wrote:This is not about transparency, The second method will avoid drawing the area of ...
OK, got it ... below a little test, proof of concept code:

Code: Select all

`' Alpha_To_ReColor.bas -- 2018-01-07, MrSwiss'' compile: -s gui'Declare Sub DrawScreen(ByVal As ULong Ptr, ByRef As Const ULong, ByRef As Const UByte)Const As UShort sw = 600, sh = 600, cd = 32, pg = 2 ' screen definitions' ===== START-MAIN =====ScreenRes(sw, sh, cd, pg)ScreenSet(1, 0)     ' double buffer setupWidth 600\8, 600\16 ' 16 x 8 Font sizeColor(&h00000000, &h00FFFFFF) : Cls ' black on white (Alpha = &h00)' local variables ... colors, counter, sleep-time, sqare-sizeDim As ULong    c1 = &hFFFF7F00, c2 = &h63636363, c3 = &hFF00FF00, c4 = &h000000FF, _                c5 = &h63FFFFFF, c6 = &h0000FFFF, c7 = &h00000000, cnt = 0, sTime = 2500, sq = 59' draw a checkered board 8 x 8 (60 x 60 pixels, border 60)For j As UInteger = 0 To 7    Var v = 60 + j * 60         ' calc. vertical pos.    For i As UInteger = 0 To 7        Var h = 60 + i * 60     ' calc. horizontal pos.        Line (v, h)-Step(sq, sq), c2, B        If cnt Mod 2 Then Paint (v + 1, h + 1), c1, c2 Else Paint (v + 1, h + 1), c3, c2        cnt += 1    Next    cnt += 1Next : Flip : Sleep(sTime, 1)' start modifying color with Alpha's value ...Dim As ULong Ptr    ps = ScreenPtr          ' get low level accessDrawScreen(ps, c4, 0)    : Sleep(sTime, 1)  ' re-color background (Alpha = 0)DrawScreen(ps, c5, &h63) : Sleep(sTime, 1)  ' re-color grid (Alpha = 63)DrawScreen(ps, c6, 0)    : Sleep(sTime, 1)  ' re-color background (Alpha = 0)DrawScreen(ps, c7, &h63)                    ' re-color grid (Alpha = 63)Locate 2, 2 : Print " press a key to QUIT ... ";' show quit msgFlip : Sleep                                ' Wait for user action before quitting' ===== END-MAIN =====Sub DrawScreen( _    ByVal sptr As ULong Ptr, _  ' a copy (of the original)    ByRef clr  As Const ULong, _' direct (read only)    ByRef chk  As Const UByte _ ' direct (read only)    )    For x As UInteger = 0 To (sw * sh - 1)  ' const's are: global!        If sptr[x] Shr 24 = chk Then sptr[x] = clr    Next : Flip     ' <-- this is for double buffered screenEnd Sub' ----- EOF -----`
nimdays
Posts: 193
Joined: May 29, 2014 22:01
Location: ID

### Re: Efficient Drawing

Thanks again MrSwiss, That's some nice boards.