Efficient Drawing

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

Efficient Drawing

Postby nimdays » Jan 02, 2018 23:51

I need your opinion about this.
The last rect is the the top most rect.

Code: Select all

type scr
    as integer w,h
    as uinteger ptr p
end type

type rect
    as integer x,y,w,h
    as ulong c
end type

sub 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 = c
end sub

sub 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 i
end sub

sub 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 sub

sub 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 sub

dim as scr sc
sc.w = 800
sc.h = 600
screenres sc.w,sc.h,32
sc.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 i

clear_scr(@sc,&h0000007f)

dim as double t = timer()

screenlock()
for i as integer = 0 to 39
    draw_rect1(@sc,@r(i))
next i
screenunlock()

print using "##.####";timer()-t

sleep 100

t = timer()

screenlock()
for i as integer = 39 to 0 step -1
    draw_rect(@sc,@r(i))
next i
screenunlock()

print using "##.####";timer()-t

sleep



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

Re: Effecient Drawing

Postby paul doe » Jan 03, 2018 0:47

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: 166
Joined: May 29, 2014 22:01
Location: ID

Re: Effecient Drawing

Postby nimdays » Jan 03, 2018 3:07

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.

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.

Code: Select all

if p[x] shr 24 = 0 then
      p[x] = r->c
end 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: 294
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Effecient Drawing

Postby paul doe » Jan 03, 2018 4:21

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 screen
cast( fb.image ptr, buffer )->pitch '' <-- gets the pitch of a pixel buffer
nimdays
Posts: 166
Joined: May 29, 2014 22:01
Location: ID

Re: Effecient Drawing

Postby nimdays » Jan 03, 2018 4:51

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 screen
cast( fb.image ptr, buffer )->pitch '' <-- gets the pitch of a pixel buffer


Thanks, I'm reading it now.
MrSwiss
Posts: 2196
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Efficient Drawing

Postby MrSwiss » Jan 05, 2018 18:12

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 Type

sub 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 With
end Sub
' end scr

type rect
    as integer  x, y, w, h
    as ulong    c
    Declare Sub init(As integer, as integer, as integer, as integer, as ULong)
end type

sub 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 With
end Sub
' end rect


' type independent sub
sub 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
    Next
End Sub


' screen and (type) sc init
dim as scr sc
With sc
    .w = 800 : .h = 600 ' type (width/height only)
ScreenRes(.w, .h, 32)   ' screen (using type)
    .p = screenptr()    ' type (screen access)
End With

' rectangle init
dim 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 start
Dim As Double   t1 = 0.0, t2 = 0.0, ts
sc._clear(&hFF00007F)  ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)

ScreenLock()
ts = Timer              ' timing 1 start
For i as UInteger = 0 to 39
    draw_rect(@sc, @r(i))
Next
t1 = Timer - ts         ' timing 1 end
screenunlock()
print using "##.####"; t1

Sleep(2500, 1)          ' wait 2.5 Sec.
sc._clear(&hFF7F0000)   ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)

screenlock()
ts = timer()            ' timing 2 start
For i as integer = 39 to 0 step -1  ' the only one 'integer', because: 'down counting-loop'
    draw_rect(@sc, @r(i))
next i
t2 = Timer - ts         ' timing 2 end
screenunlock()
print using "##.####"; t2

Sleep
' main end --- EOF ---
nimdays
Posts: 166
Joined: May 29, 2014 22:01
Location: ID

Re: Efficient Drawing

Postby nimdays » Jan 05, 2018 23:04

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 Type

sub 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 With
end Sub
' end scr

type rect
    as integer  x, y, w, h
    as ulong    c
    Declare Sub init(As integer, as integer, as integer, as integer, as ULong)
end type

sub 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 With
end Sub
' end rect


' type independent sub
sub 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
    Next
End Sub


' screen and (type) sc init
dim as scr sc
With sc
    .w = 800 : .h = 600 ' type (width/height only)
ScreenRes(.w, .h, 32)   ' screen (using type)
    .p = screenptr()    ' type (screen access)
End With

' rectangle init
dim 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 start
Dim As Double   t1 = 0.0, t2 = 0.0, ts
sc._clear(&hFF00007F)  ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)

ScreenLock()
ts = Timer              ' timing 1 start
For i as UInteger = 0 to 39
    draw_rect(@sc, @r(i))
Next
t1 = Timer - ts         ' timing 1 end
screenunlock()
print using "##.####"; t1

Sleep(2500, 1)          ' wait 2.5 Sec.
sc._clear(&hFF7F0000)   ' type embedded Sub (call as 'dim(ed)', NOT as 'written'!)

screenlock()
ts = timer()            ' timing 2 start
For i as integer = 39 to 0 step -1  ' the only one 'integer', because: 'down counting-loop'
    draw_rect(@sc, @r(i))
next i
t2 = Timer - ts         ' timing 2 end
screenunlock()
print using "##.####"; t2

Sleep
' main end --- EOF ---


Thanks, I missed a lot.

By the way, You missed the alpha checker.
Nevermind, I'll add that later.
MrSwiss
Posts: 2196
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Efficient Drawing

Postby MrSwiss » Jan 05, 2018 23:21

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: 166
Joined: May 29, 2014 22:01
Location: ID

Re: Efficient Drawing

Postby nimdays » Jan 06, 2018 22:15

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: 2196
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Efficient Drawing

Postby MrSwiss » Jan 07, 2018 13:26

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 setup
Width 600\8, 600\16 ' 16 x 8 Font size
Color(&h00000000, &h00FFFFFF) : Cls ' black on white (Alpha = &h00)
' local variables ... colors, counter, sleep-time, sqare-size
Dim 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 += 1
Next : Flip : Sleep(sTime, 1)
' start modifying color with Alpha's value ...
Dim As ULong Ptr    ps = ScreenPtr          ' get low level access
DrawScreen(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 msg
Flip : 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 screen
End Sub
' ----- EOF -----
nimdays
Posts: 166
Joined: May 29, 2014 22:01
Location: ID

Re: Efficient Drawing

Postby nimdays » Jan 08, 2018 1:01

Thanks again MrSwiss, That's some nice boards.

Return to “Beginners”

Who is online

Users browsing this forum: No registered users and 1 guest