It is currently Sat Sep 19, 2020 4:20 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Screen update speed
PostPosted: Fri Apr 06, 2018 5:38 am 
Offline
User
User
User avatar

Joined: Mon Dec 11, 2017 8:44 am
Posts: 11
Location: Australia
Hi All,

I'm writing a drawing program and need some advice or direction on how to handle screen updates. I've had a working program for a little while now and have recently re-written a large part of the program to handle flashing colour support.

To help explain my request I've cut most of the drawing bits out and just left in the main initialisation and screen update code to demonstrate what I am attempting to do which is:
* Use a 'drawing screen' buffer array which contains colour information of the picture being drawn, this holds byte values 0-15 which are used as a palette lookup
* Use a double buffered 'WindowedScreen' for displaying the drawn picture
* Use CanvasGadgets to section of the screen into 3 partitions for tools and drawing areas
* Use a WindowsTimer to update a colour table, this is used to redraw the output screen
* Use a bitmap to draw 'screen buffer' data using colour table of rgb values
* Draw the bitmap to WindowedScreen buffer and flip buffers to display smoothly
* Using PB 5.62 32bit on Windows with debugger turned off.
* Clicking in the top left window will draw random colour boxes using the predefined palette

If anyone has time to look at the code (mainly 'UpdateScreen') and explain a faster way to do it or if you think it would be better to do it another way that would be fantastic.

The performance isn't too bad but before I started using the double buffer approach the drawing and screen updating was a lot faster and smoother.

Code:
#scrW=960
#scrH=704
#drwW=640
#drwH=512

Structure Pixel
  Pixel.l
EndStructure

Structure rgbTable
  r.a
  g.a
  b.a
EndStructure

Global dMdx=160 ; current mode horizontal pixels
Global dMdy=256 ; current mode vertical pixels
Global dMpx=#drwW/dMdx   ; current mode horizontal pixel size
Global dMpy=#drwh/dMdy   ; current mode vertical pixel size

Global iBeebSCRN ; image handle
Global flashing.b=0 ; flashing colour toggle
Global flashCol.a   ; flashing colour index
Global fSpeed=540   ; flash speed in ms

Global gCur=-1      ; current gadget clicked
Global mx,my


Global Dim buf1.a(163839) ; beeb screen buffer
Global Dim bp(15)         ; beeb palette
Global Dim rgbT.rgbTable(15) ; rgb lookup table
Global Dim ct(15)            ; colour table look for redrawing main canvas
Global Dim bpFlash(15)       ; flash palette 0-7 phase 1, 8-15 phase 2


; Exit program and display a message
Procedure Exit_ART(m.s)
  If m<>""
    MessageRequester("Error", m, 0)
  EndIf
 
  End
EndProcedure

; display program stats 104,500,204,200
Procedure showstats()
  Protected x,y
  x=104+30
  y=500
 
  Box(x,y+1,90,198,bp(0))
 
  DrawText(x,y,StrU(mx,#PB_Long))
  DrawText(x,y+16,StrU(my,#PB_Long))

  DrawText(x,y+128,StrU(gCur,#PB_Long))
 
EndProcedure

; draw box outline, assumes startdrawing is already active
Procedure drawBox(x1,y1,x2,y2,c)
  FrontColor(c)
  LineXY(x1,y1,x2,y1)
  LineXY(x2,y1,x2,y2)
  LineXY(x1,y2,x2,y2)
  LineXY(x1,y1,x1,y2)
EndProcedure


;-------- Init and Load --------

If InitSprite() = 0
  Exit_ART("Cannot init Sprite subsystem!")
EndIf

If InitMouse() = 0
  Exit_ART("Cannot init Mouse subsystem!")
EndIf

If InitKeyboard() = 0
  Exit_ART("Cannot init Keyboard subsystem!")
EndIf

If OpenWindow(0,0,0,#scrW, #scrH, "ART for Windows 0.1",#PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0
  Exit_ART("Cannot init Graphics subsystem! ("+StrU(#scrW,#PB_Long)+"x"+StrU(#scrh,#PB_Long)+")") ;#scrW #scrh
EndIf

; define beeb 2 palette
Restore paletteData
For i=1 To 15
  Read.a rgbT(i)\r
  Read.a rgbT(i)\g
  Read.a rgbT(i)\b
  bp(i)=RGB(rgbT(i)\r,rgbT(i)\g,rgbT(i)\b)
Next

bp(0) = RGB(0,0,0)
rgbT(0)\r=0
rgbT(0)\g=0
rgbT(0)\b=0

; flashing palette - pointer to BP colour
For i=0 To 7
  bpFlash(i)=i 
  bpFlash(i+8)=7-i
Next

; temp buffer data - this buffer normally gets written to or modified when with drawing procedures
For i=0 To 163839
  If i<16
    buf1(i)=i % 15
  EndIf
Next

; main drawing area
iBeebSCRN=CreateImage(#PB_Any,#drwW,#drwH,32)
If StartDrawing(ImageOutput(iBeebSCRN))
  Box(0,0,639,511,bp(0))
  StopDrawing()
EndIf

; buffered drawing area 4,4,640,512
If OpenWindowedScreen(WindowID(0), 4,4, 640, 512)=0
  Exit_ART("Cannot init main canvas windowed screen object!")
EndIf

; init screen gadgets and initial state
CanvasGadget(0,0,520,648,#scrH-520) ; pallete gadget
SetGadgetAttribute(0, #PB_Canvas_Cursor , #PB_Cursor_Cross)

CanvasGadget(1,648,0,#scrW-648,#scrH) ; tool gadget
SetGadgetAttribute(1, #PB_Canvas_Cursor , #PB_Cursor_Cross)

CanvasGadget(2,0,0,648,520) ; drawing gadget (never drawn to)
SetGadgetAttribute(2, #PB_Canvas_Cursor , #PB_Cursor_Cross)

AddWindowTimer(0,0,fSpeed)

;-------- Draw controls --------

; canvas 0 - palette
If StartDrawing(CanvasOutput(0))
  Box(0,0,647,#scrH-519,bp(0))
  ;drawBox(0,0,647,#scrH-519,bp(5))
  DrawText(10,10,"Palette Gadget",bp(2)) 
  StopDrawing()
EndIf

; canvas 1 - tools
If StartDrawing(CanvasOutput(1))
  ; clear canvas to black
  Box(0,0,#scrW-648,#scrH,bp(0))
 
  ;drawBox(0,0,#scrW-647,#scrH-1,bp(3))
 
  DrawText(10,10,"Tools Gadget",bp(2))
 
  ; stats
  x=104
  y=500
  DrawText(x,y,"mX:")
  DrawText(x,y+16,"mY:")
  DrawText(x,y+32,"pX:")
  DrawText(x,y+48,"pY:")
  DrawText(x,y+64,"mB:")
  DrawText(x,y+80,"mA:")
  DrawText(x,y+96,"CT:")
  DrawText(x,y+112,"TS:") 
  DrawText(x,y+128,"gC:")     
     
 
  StopDrawing()
EndIf

; canvas 2 - drawing area
If StartDrawing(CanvasOutput(2))
  ; clear canvas to black
  Box(0,0,647,519,bp(0))
 
  ; main canvas double border
  ;drawBox(0,0,647,519,bp(1))
  ;drawBox(1,1,646,518,bp(1))
 
  StopDrawing()
EndIf


If StartDrawing(ScreenOutput())
  DrawImage(ImageID(iBeebSCRN),0,0)
  StopDrawing()
EndIf

FlipBuffers()


;-------- MainLoop --------

Repeat
 
  ; event loop
  Repeat
   
    Event = WindowEvent()
   
    Select event
      Case #PB_Event_Timer  ; handle flashing colours
        flashing=(flashing+1) & 1
       
        ; update flashing colour pointer
        For i=0 To 7
          If flashing
            bpFlash(i+8)=7-i
          Else
            bpFlash(i+8)=i
          EndIf
        Next
       
      Case #PB_Event_Gadget ; gadget events
        gCur=EventGadget()
       
        ; set mouse action if none already set for left mouse click
        If EventType() = #PB_EventType_LeftButtonDown
          ; handle general lb event
         
        EndIf
       
        ; determine which gadget has triggered an event
        Select gCur
           
            ;-------- Palette Gadget Area --------
          Case 0
            mx = GetGadgetAttribute(gCur, #PB_Canvas_MouseX)
            my = GetGadgetAttribute(gCur, #PB_Canvas_MouseY)
           
            ; left click or mouse down / move events
            If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(gCur, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
              ; handle general lb and lb move event for gadget 0
             
            EndIf
           
            ;-------- Tools Gadget Area --------
          Case 1 ; tools area
            mx = GetGadgetAttribute(gCur, #PB_Canvas_MouseX)
            my = GetGadgetAttribute(gCur, #PB_Canvas_MouseY)
           
            If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(gCur, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
              ; handle general lb and lb move event for gadget 1
             
            EndIf
           
            ; left button release events
            If EventType()=#PB_EventType_LeftButtonUp
              ; handle general lb up gadget 1
             
            EndIf
           
            ;-------- Drawing Gadget Area --------
          Case 2 ; drawing area
            mx = GetGadgetAttribute(gCur, #PB_Canvas_MouseX)
            my = GetGadgetAttribute(gCur, #PB_Canvas_MouseY)
           
            If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(gCur, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
              ; handle general lb and lb move event for gadget 2
             
              ; update pixels in buf1
              c=Random(15)
              m=ArraySize(buf1())
             
              xs=(mx-16) / dMpx
              ys=255-((my+4) / dMpy)
             
              For y=0 To 10
                For x=0 To 5
                  a=(y+ys)*640+x+xs
                  If a>-1 And a<m
                    buf1((y+ys)*640+x+xs)=c
                  EndIf
                 
                Next
              Next
             
            EndIf
           
            ; left button release events
            If EventType()=#PB_EventType_LeftButtonUp
              ; handle general lb up gadget 2
             
            EndIf
           
        EndSelect
       
        ; left general button release events
        If EventType()=#PB_EventType_LeftButtonUp
          ; handle general lb up
         
        EndIf
       
      Case #PB_Event_CloseWindow ; close application event 
        End
       
    EndSelect
   
   
  Until event=0
 
  ;-------- Update Screen --------
 
  ; update screen
  If StartDrawing(ImageOutput(iBeebSCRN))
    Buffer      = DrawingBuffer()             ; Get the start address of the screen buffer
    Pitch       = DrawingBufferPitch()        ; Get the length (in byte) took by one horizontal line
    PixelFormat = DrawingBufferPixelFormat()  ; Get the pixel format.
   
    ; configure palette for RGB or BGR
    If PixelFormat = #PB_PixelFormat_32Bits_RGB
      For i=0 To 15
        ct(i)=bp(bpFlash(i))
      Next
    Else ; Else it's 32bits_BGR
      For i=0 To 15
        ct(i)=rgbT(bpFlash(i))\b+rgbT(bpFlash(i))\g<<8+rgbT(bpFlash(i))\r<<16
      Next
    EndIf
   
   ; beeb pixels are 4 screen pixels wide by 2 screen pixels high
    For y = 0 To 511
      *Line.Pixel = Buffer+Pitch*y
      yMul=(y/2)*640
     
      For x=0 To 159
        dc = ct(buf1(x+yMul))
       
        *Line\Pixel = dc ; Write the pixel directly to the memory !
        *line+4
        *Line\Pixel = dc ; Write the pixel directly to the memory !
        *Line+4
        *Line\Pixel = dc ; Write the pixel directly to the memory !
        *Line+4
        *Line\Pixel = dc ; Write the pixel directly to the memory !
        *Line+4
       
      Next
    Next
    StopDrawing()
  EndIf
 
  ; draw beeb screen on screen buffer
  If StartDrawing(ScreenOutput())
    DrawImage(ImageID(iBeebSCRN),0,0)
    StopDrawing()
  EndIf
 
  ; update tools
  If StartDrawing(CanvasOutput(1))
   
    ; show stats
    showstats()
   
    StopDrawing()   
  EndIf
 
  FlipBuffers()
 
  ExamineKeyboard() ;Keyboard
 
Until KeyboardPushed(#PB_Key_Escape)

End


;
;-------- Data Section --------
;         

DataSection
 
  ; palette Data
  paletteData:
  Data.a 255,000,000,000,255,000,255,255,000,000,000,255,255,000,255
  Data.a 000,255,255,255,255,255,128,128,128,192,000,000,000,192,000
  Data.a 192,192,000,000,000,192,192,000,192,000,192,192,192,192,192
 
EndDataSection


; colour map, flashing colour default is 540ms
; 0   black
; 1     red
; 2     green
; 3   yellow
; 4     blue
; 5     magenta
; 6     cyan
; 7     white
; 8     flashing black-white
; 9     flashing red-cyan
; 10   flashing green-magenta
; 11   flashing yellow-blue
; 12   flashing blue-yellow
; 13   flashing magenta-green
; 14   flashing cyan-red
; 15   flashing white-black


Top
 Profile  
Reply with quote  
 Post subject: Re: Screen update speed
PostPosted: Fri Apr 06, 2018 7:24 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jun 24, 2004 8:51 am
Posts: 1483
Location: Germany
why you don't draw directly on the screen?

_________________
Belive!
<Wrapper>4PB, PB<game>, =QONK=, PetriDish, Movie2Image, PictureManager,...


Top
 Profile  
Reply with quote  
 Post subject: Re: Screen update speed
PostPosted: Fri Apr 06, 2018 8:44 am 
Offline
User
User
User avatar

Joined: Mon Dec 11, 2017 8:44 am
Posts: 11
Location: Australia
IceSoft wrote:
why you don't draw directly on the screen?

Couple of questions for this approach:
* Can I do this in realtime while updating the drawing buffer and other tools every frame?
* There are quite a lot of things happening in realtime such as buttons, labels, stats, flashing colours etc. and I need to redraw the drawing frame and respond to mouse controls as frequently as possible to make it all smooth.
* can you point me to an example of this approach, I'm pretty new to PB so while I understand what you're saying I've not seen this approach in the help or demo code.

I am willing to rewrite the guts of the program for the right approach so any advice would be helpful for me to try out but I just need a little assistance to get started, mostly with a fast buffer draw routine and using mouse input from direct screen updates.


Top
 Profile  
Reply with quote  
 Post subject: Re: Screen update speed
PostPosted: Fri Apr 06, 2018 8:52 am 
Offline
Addict
Addict
User avatar

Joined: Mon Jul 25, 2005 3:51 pm
Posts: 3741
Location: Utah, USA
Here are two things that can be done (whether for image or screen drawing).

Both changes have to do with pixel size. First, change the pixel structure to include 4 bytes instead of one. Second change the drawing loop to duplicate the even numbered lines to the odd numbered lines.

Here's just the code for those changes:
Code:
Structure Pixel
  ;Pixel.l
  Pixel.l[4]
EndStructure


and the drawing update loop
Code:
   ; beeb pixels are 4 screen pixels wide by 2 screen pixels high
    For y = 0 To 511
      *Line.Pixel = Buffer+Pitch*y
      yMul=(y/2)*640
      If y & 1
        ;if an odd line, copy previous line
        CopyMemory(*Line - Pitch, *line, 160 * SizeOf(Pixel))
      Else
        For x=0 To 159
          dc = ct(buf1(x+yMul))
         
          *Line\Pixel[0] = dc ; Write the pixel directly to the memory !
          *Line\Pixel[1] = dc ; Write the pixel directly to the memory !
          *Line\Pixel[2] = dc ; Write the pixel directly to the memory !
          *Line\Pixel[3] = dc ; Write the pixel directly to the memory !
          *Line+SizeOf(Pixel)
         
        Next
      EndIf
    Next


I didn't do any timing tests to compare. It should be faster in theory at least. :)

_________________
Image


Top
 Profile  
Reply with quote  
 Post subject: Re: Screen update speed
PostPosted: Sat Apr 07, 2018 9:59 am 
Offline
User
User
User avatar

Joined: Mon Dec 11, 2017 8:44 am
Posts: 11
Location: Australia
Demivec wrote:
Both changes have to do with pixel size. First, change the pixel structure to include 4 bytes instead of one. Second change the drawing loop to duplicate the even numbered lines to the odd numbered lines.
...
I didn't do any timing tests to compare. It should be faster in theory at least. :)

I like both these approaches! Something new to play with, I've tried it out but I didn't notice much difference but I'll setup some timing code and do comparisons.

Thanks for offering some suggestions, this is exactly what I need to try something different and new :D


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye