Images - Getting the best performance

By: Kevin Picone




What's This ?


     The following is a collection of tutorial / discussions taken from the PlayBASIC forums. For the most part, they're designed to outline some of the do's and dont's about Images, Maps & Sprites in terms of performance. How well you understand them, can make a huge difference to the quality of programs you'll be able to produce.

      Since the material covered here is quite technical, we highly recommend picking over the provided samples and re-reading it as many times as necessary.



I N D E X:







What Image Formats can I load ?



      The PlayBASIC image loader(s) currently supports a subset of common image formats plus it's own Image format PBI.


Windows .BMP

1 bit
4 bit (raw & RLE)
8 bit (raw & RLE)
16bit
24bit
32bit

TGA formats

8 bit (raw & RLE)
16bit (raw & RLE)
24bit (raw & RLE)
32bt (raw & RLE)

PNG
8bit
24bit
32bit.

JPEG



      Alpha channel is supported for PBI, BMP, TGA & PNG images. See LoadAFXimage / LoadImage for loading images with alpha channel.

Top






Can I load all permutations of common Image Files ?


      No. The internal image loading library only supports the most common file specifications at the time of image loaders were written. Therefore there are BMP, TGA, PNG and JPEG files it will not load out of the box. This is not uncommon as most so called 'game' image loaders have similar limitations to keep the library sizes down. So you might need to convert some files in order to use them. The package comes with a version of the FreeImage libraries, which includes various saving routines for formats like BMP, PNG, JPG (See FreeImage_LoadImage, FreeImage_SaveJPG, FreeImage_SavePNG , FreeImage_SaveBMP )

Top







What are PBI image files ?


      PBI is PlayBASIC's very own image format. The format is designed primarily as a compressed 32 bit lossless format for 2D game images. The compression is only light though, focusing mostly on zone based colour and area duplications, which often appear in animations and tile maps. The light compression allows PBI files to load quickly (about the same or faster than BMP / TGA files) as well archiving ( Zip / RAR / 7zip) very well, generally much better than PNG files, meaning you can save a lot of file size in your final games distribution by swapping to PBI format. You also get the added bonus of PBI not being a 'common' place format, so only people with access to PlayBASIC would be able to load none encrypted images.

      You can load files using the standard LoadImage commands. To save an image to disc in PBI format you'll need to the use the SavePBI command.


Top






Video Cards like Big Blit's


      Even if you've only been programming for a short while, you've perhaps noticed a strange anomaly when drawing (bliting) images. Which is, why does the blitter (the image drawer) seem to choke up drawing a lots of small images, when it can throw around huge ones easily ?

      To answer this, we have to look at how Windows give us control of the video hardware. It should be noted, that we're primarily discussing the rendering of Video Images (those stored into your graphics cards video memory) and not those in system memory (FX/AFX image types).

      Your PC has what's termed a blitter. You can think of this as the part of the graphics chip solely designed to draw / copy rectangular graphic data very quickly. Now every time you create a image (in video memory) and render it. PlayBASIC uses the blitter device to transfer the pixel information for you. Now this is all lovely, but there's a catch ! The Blitter is a shared device, and we're not the only one's using it! (Remember, Windows + any other program running in the background are also using it.)

      Since the blitter is shared, when we want to draw (blit) some graphics, PlayBASIC is forced to wait inline for the blitter to become available (from either a pervious draw call, or some other program / task is using it). Once it's free, we can send it our drawing job and continue on our way. The drawing will take place while our program continues running. This is called asynchronous rendering. Which is fancy way of saying the graphics chip is drawing, while the main computer CPU continues on doing something else, such us running our program code. (Note: Not all video cards support this!)

      The issue is that if we call the blitter frequently, we're inevitably going end up stalling our program in wait loops, while DirectX waits for the graphics cards Blitter to become available to us. This is what occurs when we're try and draw lots of small images with the blitter. While the drawing might be quick once acquired, all this polling & waiting around for the blitter equals one sure thing, lots of wasted time. Which can really impact performance. You've probably noticed this when drawing Maps with really small blocks for example.

      Lets demonstrate. In the example bellow were going to render a tiled image to the screen and monitor the FPS. Obviously newer GPU's with faster blitters will cope better with this, than older ones, but this doesn't mean the issue is gone, just that it'd impacting those users little less.

      In this example we'll draw a tiled image with 8*8 tiles, 16*16, 32*32, 64*64, 128*128, 256*256 blocks etc etc then monitor the average FPS at these sizes.


  
  
  OpenScreen 800,600,32,2
  
  Seconds=5
  Maxtests=6
  
  Type tFrame
     Afps#
     Frames
     Size
  EndType
  
  Dim Info(Maxtests) As tFrame
  
  TestCount=0
  BlockSize =8
  
  Repeat
     
     Cls RGB(0,0,0)
     c1=RGB(255,0,0)
     c2=RGB(255,255,255)
     c3=RGB(0,0,255)
     c4=RGB(0,255,0)
     ShadeBox 0,0,BlockSize,BLockSize,c1,c2,c3,c4
     GetImage 1,0,0,BlockSize,BlockSize
     EndTime=Timer()+Seconds*1000
     frames=0
     Repeat
        Inc frames
        TileImage 1,Xpos,Xpos,false
        Xpos=Mod(Xpos+1,BlockSize)
        
        Info(testCount).frames     =frames
        Info(testCount).Size          =BlockSize
        Text 0,0,Str$(FPS())+"  Block Size:"+Str$(BlockSize)
        Sync
     Until Timer()>EndTime
     
     BlockSize=BlockSize*2
     Inc testCount
  Until TestCount>=Maxtests
  
  
  Cls RGB(0,0,0)
  Print "Results"
  
  For lp=0 To Maxtests-1
     f#=info(lp).frames
     f$=Digits$(f#,5)
     fr$=Str$(f#/seconds)+"  Size:"+Str$(info(lp).Size)
     m$=Digits$(lp,2)+"  Frames:"+F$+"  Fps:"+fr$
     Print m$
  Next
  Sync
  WaitKey
  


Results: (Duron 800 mhz & GeForce 2 MX200) ( 1999/2000 computer)

  
  00  Frames:00050  FPS:10.0   Size:8
  01  Frames:00193  FPS:38.6   Size:16
  02  Frames:00572  FPS:114.4  Size:32
  03  Frames:00721  FPS:144.2  Size:64
  04  Frames:00746  FPS:149.2  Size:128
  05  Frames:00755  FPS:151.0  Size:256
  



Results: (AMD 64FX 3000 mhz & GeForce 6600GT) (2005/2006 computer)

  
  00  Frames:00125  FPS:25.0    Size:8
  01  Frames:00480  FPS:96.0    Size:16
  02  Frames:01628  FPS:325.6   Size:32
  03  Frames:04519  FPS:903.8   Size:64
  04  Frames:05839  FPS:1167.8  Size:128
  05  Frames:06477  FPS:1295.4  Size:256
  




      OK, Notice how that even though the program is drawing the same amount of pixels, the smaller the block sizes, the more the program chokes up ?

      The best solution for overcoming such problems, might be to use larger tiles, or be more selective how and when you refresh the entire screen.

Top







A crash course in Image & Sprites Draw Modes


      One the most misunderstood aspects of PlayBASIC (among other things), is how to design your program to take advantage of Image & Sprite draw modes (SpriteDrawMode. Draw mode gives us control over how the sprites are rendered. This is nice and all, but certain render modes can place additional stress on your program if you're not careful. Making the program slower than need be. This most commonly occurs when using the Alpha Blended modes. In fact, it'll effect any draw mode that has to read from the destination surface.

      Getting the best out it, comes down to how well you understand the different types of image buffers PlayBASIC offers us. Today (PlayBasicV1.64 and bellow) we have 2 primary image types. ( note: future editions of PlayBASIC have more).


Image Type #1 - Video Image

      Video Images are images where the pixel data is stored in your computers graphics card memory. These images can be copied / drawn to the screen (which is also in your video cards memory) very quickly, since they utilize you've video cards blitter. Which is the part of the GPU specially designed for this purpose.

      While it's fast to transfer Images around in video memory with the blitter (on most cards), the blitter has it's fair share of limitations. Those being, that it can basically only Copy & fill rectangles of pixels, and that's about it. So it's not very interesting.

      So all other rendering is in the hands of the CPU. While the CPU can write data to images in video memory very quickly, it can't read from them. Effectively reading from video memory is 20->30 times slower than writing! Even worse on some systems. Most people no doubt assume this is a PlayBASIC thing, it's not, it's limitation of how the PC was designed. It doesn't matter what language you use, we just can't write or read from video memory at the same rate.

      Basically, Video images are our best option if we want to draw loads of solid (no alpha), static sprites (not rotated) around the screen.



Image Type #2 - FX Image

      FX images are a variation of normal images. The primary difference however, is that the Pixel data is stored in your computers main memory. While there's no visible difference between the two, they do give us a different set of abilities.

      Being stored in system memory grants us the freedom of faster access to the pixels in the image. So we can we can read & write pixels as fast as our CPU can manage. But there's a price, FX images are slower to draw to the display screen. Since the drawing has to be performing using the CPU. We can't use the video cards blitter, since it was designed to work with image data stored in video memory, not system memory.

      Now since FX's images are stored in system memory, this gives the added ability to draw them rotated / scaled in real time. This is possible as the software rotation code can read the pixels from the image as fast as CPU / Memory will allow. We couldn't do this as fast, if the image was stored in video memory. You can try that yourself. LoadImage "myIMageNameHere",1, then try and draw it rotated.... it'll be slow for the aforementioned reason. Then try it with an FX image.



Common Mistakes

      OK, so we've established that if we want to rotate an image or read from an image a lot, then FX images are probably our bet at this time. But what about rendering translucence styled image effects such as Alpha Blending, Alpha Addition, Alpha Subtract, Logical operations etc... ?

      This is where the most common mistakes are made! I.e. A new user loads up an FX image and tries to alpha blend it to the screen. First thing they notice that's nice and slow! To explain why, we'll examine the basic process that's being performed when we blend images together..


      For each pixel we're doing the following.

  
  
  Step #1 Read a src pixel from the image were drawing
  
  Step #2 Read the corresponding Dest Pixel from the
  destination image (that one we're going To
  overwrite/blend with)
  
  Step #3  Perform the blending operation.
  
  Step #4  Output the newly blended pixel To the destination image.
  
  


      Now that seems simple enough, so what are we missing ?

      Notice how that in order to blend a pixel, we have to the read pixels from the destination image ? Hmmm, well what if that destination is in Video memory ? Wouldn't all that reading video memory slow our drawing routine down ? Yep, it certainly will !

      While you can get away with blending small images directly to the screen or video images, the better approach, if you want a heavy amounts of blending, would be to draw your screen to a screen sized FX image and do all your blending stuff on that. Then once you're done, transfer (draw) that FX image to the screen. This will avoid video memory reading completely.

      The upside of this approach is that we get much faster Alpha blending. However, we do loose the assistance of the video cards blitter while doing this. So commands like CLS/BOX & drawing solid images/map will be slower. How slow, depends on how fast your cpu/memory is, and don't forget we have to transfer the whole image to the screen. But even with this added Burdon, it's still way faster than attempting to render alpha blend effects directly to video memory.


Example

      This example shows the process of rendering sprites to an FX image, then drawing the image the screen so we can see it. Those with a keen eye will notice it's a variation of the Alpha sprite example that comes in the PlayBASIC example pack. The main difference is the scrolling backdrop isn't present in this version.

      Anyway, I've provided the example so you can get an idea of how much FX image blitting your system can push around. I recommend experimenting with the sprite particle size, screen depth. Every system will have a balancing point.


  
  
  Global   Use_FX_Buffer          = true
  Constant Particle_Size          =32   ; try 16, 24, 32, 48, 64, 96, 128
  Constant RequiredFrameRate     =30
  
  
  OpenScreen 640,480,32,2
;     OpenScreen 640,480,16,2
  
  #Include "BlitIMage"
  
  MakeBitmapFont 1,$ffffff
  
  sw=GetScreenWidth()
  sh=GetScreenHeight()
  
  Dim ParticleImages(4)
  Size=Particle_Size
  ParticleImages(0)=MakeParticle(size,RGB(255,RndRange(100,200),Rnd(75)))
  ParticleImages(1)=MakeParticle(size,RGB(255,RndRange(20,40),Rnd(15)))
  ParticleImages(2)=MakeParticle(size,RndRGB())
  ParticleImages(3)=MakeParticle(size,RndRGB())
  ParticleImages(4)=MakeParticle(size,RndRGB())
  
  
  
  
  Type tObject
     Status
     x#,y#
     xdir#,ydir#
     sprite
     rotspeed#
  EndType
  
  max=10
  Dim Objects(max) As tobject
  
  Gosub INit_Objects
  
  
  
  Screen=NewFXImage(sw,sh)
  
; ------------------------------------------------------------------
;  Start of Main Loop
; ------------------------------------------------------------------
  
  Do
     Gosub Update_Logic
     Gosub Render_Scene
     Sync
  Loop
  
  
  
` *=----------------------------------------------------------------------=*
`                               >> Update Sprites Rebound Logic <<
` *=----------------------------------------------------------------------=*
  
Update_logic:
  For lp=0 To max
     If  Objects(lp).status
        spr=Objects(lp).sprite
        MoveSprite spr,objects(lp).xdir#,objects(lp).ydir#
        If SpriteInRegion(spr,0,0,sw,sh)=false
           If GetSpriteX(spr)<0
              objects(lp).xdir#=objects(lp).xdir#*-1
           EndIf
           If GetSpriteX(spr)>sw
              objects(lp).xdir#=objects(lp).xdir#*-1
           EndIf
           If GetSpriteY(spr)<0
              objects(lp).ydir#=objects(lp).ydir#*-1
           EndIf
           If GetSpriteY(spr)>sh
              objects(lp).ydir#=objects(lp).ydir#*-1
           EndIf
        EndIf
        TurnSprite spr,objects(lp).rotspeed#
     EndIf
  Next
  
  If UpKey()
     max=max+10
     Gosub INit_Objects
  EndIf
  
  
  If DownKey() And max>10
     max=max-10
     Gosub INit_Objects
  EndIf
  
  Return
  
  
  
` *=----------------------------------------------------=*
`             >> Render The Current Scene <<
` *=----------------------------------------------------=*
  
  
Render_Scene:
  ClsColour=RGB(110,140,170)
  
  If Use_FX_Buffer=true
     RenderToImage screen
  Else
     Cls ClsColour
  EndIf
  
; Draw the Sprites
  DrawAllSprites
  
  If Use_FX_Buffer=true
     RenderToScreen
   ; render the FX screen to the real screen
     BlitImageClear(Screen,0,0,ClsColour)
  EndIf
  
  
  If Use_FX_buffer=false
     t$="[Video Render] "
  Else
     t$="[FX Render] "
  EndIf
  
  Text 0,0,t$+Str$(max)+" Sprites @ "+Str$(CurrentFPS)+"fps"
  
  If EnterKey()
     Use_FX_Buffer=1-Use_FX_Buffer
     FlushKeys
  EndIf
  
  If SpaceKey()
     SetCursor 0,20
     Pixels=Max*(Particle_Size*Particle_Size)
     Print " Blended Pixels :"+Str$(pixels)
     Print "Dots Per Second :"+Str$(Pixels*CurrentFPS)
  EndIf
  
  
; Check the fps, if it's over our target, then
; add more sprites to the scene
  CurrentFps=FPS()
  If Timer()>CheckFpsTime
     CheckFpsTime=Timer()+250
     If (CurrentFps-1)=>RequiredFrameRate
        max=max+2
        Gosub Init_Objects
     EndIf
  EndIf
  
  Return
  
  
  
` *=------------------------------------------------------=*
`                >> INIT/CREATE Sprites <<
` *=------------------------------------------------------=*
  
  
Init_Objects:
  For lp=max+1 To GetArrayElements(Objects().tobject,1)
     If  Objects(lp).status
        Objects(lp).status=false
        DeleteSprite Objects(lp).sprite
     EndIf
  Next
  
  If max>GetArrayElements(Objects().tobject,1)
     ReDim Objects(max) As tobject
  EndIf
  
  For lp=0 To max
     If  Objects(lp).status=false
        
        Objects(lp).status=true
        x=50+Rnd(sw-100)
        y=50+Rnd(sh-100)
        
        Angle#     =Rnd(360)
        Speed#     =RndRange(1,5)
        Objects(lp).xdir#=CosRadius(angle#,speed#)
        Objects(lp).ydir#=SinRadius(angle#,speed#)
        
        zz=Rnd(4)
        Select zz
            Case 0
                ThisImage=ParticleImages(0)
                DrawMode=2+16
                transparent=on
            Case 1
                ThisImage=ParticleImages(1)
                drawMode=2+32
                transparent=off
            Case 2
                ThisImage=ParticleImages(2)
                drawMode=2+16
                transparent=off
            Case 3
                ThisImage=ParticleImages(3)
                drawMode=2+8
                transparent=on
                
            Case 4
                ThisImage=ParticleImages(4)
                drawMode=2+4
                transparent=on
                Alphalevel#=Rnd#(1)
        EndSelect
        
        spr=NewSprite(x,y,thisimage)
        AutoCenterSpriteHandle Spr,true
        SpriteDrawMode Spr,drawmode
        SpriteTransparent spr,transparent
        SpriteAlphaLevel spr,AlphaLevel#
      ; Only has effect when sprite is
      ; set to alpha draw mode
        Objects(lp).sprite          =Spr
        objects(lp).rotspeed#     =RndRange#(1,5)
     EndIf
  Next
  
  Return
  
  
` *=------------------------------------------------------=*
`                 >> Make particle Image <<
` *=------------------------------------------------------=*
  
Function MakeParticle(Size,Col)
  ThisImage=NewFXImage(Size,Size)
  RenderPhongImage  ThisImage,Size/2,Size/2,col,255,260/(size/2)
EndFunction ThisImage
  



Keys

Enter = Toggle between Render to an FX image or rendering Directly to Video memory.

Space = See basic filler stats on your machine.


Results

      All test were conducted in 640*480 (full screen exclusive) display mode in both 16 & 32bit modes. The test tries to calc how many sprites of size X, can be on screen while holding steady 30fps on the machine. All sprites are rotating, but have randomly assigned an alpha draw modes.



800mhz Duron & GF2 mx200

* 32bit
  
  Sprite Size [16]   =     764
  Sprite Size [32]   =     336
  Sprite Size [64]   =      118
  Sprite Size [128]   =     38
  


* 16 bit
  
  Sprite Size [16]  =      908
  Sprite Size [32]  =      422
  Sprite Size [64]  =      166
  Sprite Size [128=     56
  




3gig AMD 64 & GF6600

* 32bit
  
  Sprite Size [16]   =    3200
  Sprite Size [32]   =     1558
  Sprite Size [64]   =     630
  Sprite Size [128]   =   200
  



* 16 bit
  
  Sprite Size [16]  =    3418
  Sprite Size [32]  =    1690
  Sprite Size [64]  =      668
  Sprite Size [128=    244
  


Top






Copying/Drawing Between Images Types


      A good rule of thumb when working out how to arrange your image data in memory, is to always keep them in the same format all the way through the drawing process. This is not always possible, as how you render will also determinate what format the image needs to be held in. While the performance will vary system to system, here's some general tips on the subject.


      Also See: PrepareFXImage , PrepareAFXImage


Image Type Key

VI = Video Image
FX = FX image


Performance Guide when Drawing fixed sized solid/transparent images

1) Copying VI to VI = FASTEST - Assisted by the Graphics Card Blitter.
2) Copying VI to FX = VERY SLOW - Reads from the video memory. *
3) Copying FX to VI = GOOD - CPU driven.
4) Copying FX to FX = GOOD - CPU driven.


Performance Guide when Drawing Rotated/scaled images


1) Copying FX to FX = FASTEST - CPU driven. (and no buffer lock stalls)
2) Copying FX to VI = FAST - CPU driven.
3) Copying VI to VI = VERY SLOW - Reads from the video memory. *
4) Copying VI to FX = VERY SLOW - Reads from the video memory. *




Performance Guide when Drawing Blended (Alpha/Add/Sub/50 etc etc ) images

1) Copying FX to FX = FASTEST - CPU driven.
2) Copying VI to VI = EXTREMELY SLOW - Reads from both video memory buffers. ***
3) Copying VI to FX = VERY SLOW - Reads from the source video memory. *
4) Copying FX to VI = VERY SLOW - Reads from the destination video memory. *


* = AVOID IF POSSIBLE
*** = AVOID AT ALL COSTS

Top






Locking / Unlocking Buffers - Where and When ?


      Unlike the good old days of the 8/16 and early 32bit machines, when we write programs on the PC, were not alone! As while our program is running, there are other background operating system tasks & program running also. This means our PlayBASIC programs have to share system resources with other tasks. So windows act's as a mediator of sorts. Allocating time for our program to use certain device and then doing the same of other programs.

      Primarily when we think about shared resources in the computer, we're thinking of Image Data, Hardware devices (mouse/keyboard/joystick/ Image Blitter/ 3D hardware /Sound etc etc ) and memory. While the majority of those are transparent to the PlayBASIC programmer (as we're hidden the tedious tasks away), it is very advantageous to have some understanding of how windows manages the key ingredients in your games, AKA your images.

      Hopefully, you've aware that we have two or more primary types of images that our PB programs can create. Images stored in Video memory & FX images (image stored in system memory) We won't concern our selves with when/why we should use either, or both, we just want to get some idea of how windows handles resources for us.

      Lets start from the start. We when create a program we're also creating the screen graphics device. To the user the screen is the output display of what our program has been drawing. Behind the scenes, it actually handles various other devices for us also, but basically to the user it's nothing more than a big image. The screens image will be stored in your computer Video Memory. Which allows your computers graphics card to display it on your monitor, or even move it around in the video memory easily if need be. Yes, because video memory is shared commodity, Windows can move stuff around when it's not being used !

      So how does this affect our programs ? Well, because nothing is nailed down inside windows, PlayBASIC has to constantly ask Windows prior to accessing any of it's resources.


      Lets look at example. Often one of the first programs people write is something simple to render a bunch vector graphics elements to the screen. In our example here we'll draw 5000 dots.

  
  OpenScreen 800,600,32,1
  
  Do
   ; clear the screen to black (rgb(0,0,0)
     Cls RGB(0,0,0)
     
   ; draw a 5000 dots to the screen
     For lp=0 To 5000
        Dot Rnd(800),Rnd(600)
     Next
     
   ; Show how fast the screen is updating
     Print FPS()
     
   ; show this screen image to the user.
     Sync
  Loop
  


      This program creates a 800*600 display, draws 5000 dots to the screen and shows just how fast your computer can update the screen, or does it ? I guess this comes from the assumption that we all think our computers are ultra fast today. However, if you tried that demo you'll no doubt get a shock. It'll crawl!

      Why ?

      Now remember when we said that screen/images are shared resources? Well, the problem in this case, is that every time we draw a single dot to the screen, PlayBASIC has to beg windows for access to the screen. This begging process in windows speak, is called Surface Locking.

      So in order to draw a single dot, PB has do the following.

  
  Step 1) Request Lock on the screen surface And Wait For it To be locked
  Step 2) Draw the Dot
  Step 3) Unlock the screen surface.
  


      In the case of rendering a DOT, steps 2 & 3 are trivial, the bottle neck occurs in step 1.

      When PB requests a lock on the surface, we're at the total mercy of windows to react quickly to this request each time. Some times the locking is completed virtually instantly, but it generally seems to take anywhere from 1/2 millisecond to a few milliseconds or even more. This might not sound like much time, but when we consider there's only 1000 milliseconds in one full second, and were going to be wasting the majority of that just locking and unlocking this surface constantly.

      Clearly there must be better way.

Top





User Controlled Buffer Locking / Unlocking


      The solution to such problems lies firmly in the users hands. If you know your going to be drawing a batch of GFX items (as per our previous example) then rather than force PB to constantly request a lock on the current surface each time it draws an item, you could do the locking and unlocking yourself. To do this, we use the LockBuffer & UnlockBuffer commands.

      Lockbuffer will lock the current surface were drawing to. The surface will remain locked until you call it's partner command UnlockBuffer. It should be noted, that it's not advisable to leave a surface locked indefinitely! Windows tends can get very upset and close your program. So prior to your drawing batch lock the surface, do your drawing, then unlock it again.

      Lets put this new found knowledge to test and expand the previous example to include them. This time we'll include Lock Buffer prior to draw our batch of dots, and the unlock once were done.


  
  OpenScreen 800,600,32,1
  
  Do
   ; clear the screen to black (rgb(0,0,0)
     Cls RGB(0,0,0)
     
   ; Lock the Current Buffer
     LockBuffer
     
   ; draw a 5000 dots to the screen
     For lp=0 To 5000
        Dot Rnd(800),Rnd(600)
     Next
     
   ; now we unlock it.
     UnLockBuffer
     
   ; Show how fast the screen is updating
     Print FPS()
     
   ; show this screen image to the user.
     Sync
  Loop
  


Top






Are there times when I shouldn't use lockbuffer ?


      Yes, unfortunately when we lock a surface there's few by-products of this. While locking ensures that windows won't try and move the surface while we're drawing to it, it also restricts other devices from doing anything to the surface until we've released our control over it. This will mainly affect any rendering functionality that requires the graphics card GPU / blitter.

      Some general guides when you've locked a surface, will be to avoid attempting to the draw the following to that locked surface.


* Drawing Windows Text (True type fonts)
* Draw Video Images /3D image to the screen.
* Cls / Box or any hardware accelerated primitives like polygons/boxes/rotated images.


      While nothing bad should happen, what's likely to the occur is that item your drawing will unlock the before it starts to draw, or it'll simply refuse to draw anything since the surface was locked.

Top




 
Related Info: CameraBasics | DrawRotatedImage | LoadFXImage | LockBuffer | Maps | SavePBI | SpriteDRawMode | Sprites :
 


(c) Copyright 2002 - 2024 - Kevin Picone - PlayBASIC.com