vrm@blackwater.cerc.wvu.wvnet.edu (Vasile R. Montan) (05/18/91)
I am in the process of writing a program that does some pretty complicated animation. In the version of the program I've got now, things are just running too slow. I've got to figure out how to make things run faster. (I'm already on an 030 machine with a math coprocessor, so running this program on, say, a Plus would be just intolerable.) I'd like to run my scheme past you; could you all please suggest places where I could speed things up? In this animation, I am moving icons around on the screen. I have two offscreen bitmaps. The first offscreen contains the background art, which is slow to draw; this way, I only have to draw it once. I continually CopyBits this whole bitmap into the second bitmap. I draw the icons the second bitmap, then copyBits the second bitmap onto the screen. This whole process happens every event loop. (Slow as this sounds, I have reason to believe that this is actually not the big time-consumer.) Each time I plot an icon, I GetIcon it, then draw it using copyBits, then ReleaseResource it. Now, if I'm not mistaken, this doesn't actually purge the icon from memory, right? If something else needs the memory it will write over it, but if nobody needs the memory, the icon will hang around until the next cycle, and GetIcon will just give me a handle to the icon in memory, right? In doing the calculations for the animation, I frequently refer to complex data structures by handles. Is this a particularly slow way of doing things? Could I speed things up appreciably by locking the handles and using more Pascal WITH statements? Any suggestions? --Kurisuto un020070@vaxa.wvnet.edu
2fmlcalls@kuhub.cc.ukans.edu (05/18/91)
In article <1776@babcock.cerc.wvu.wvnet.edu>, vrm@blackwater.cerc.wvu.wvnet.edu (Vasile R. Montan) writes: > all please suggest places where I could speed things up? > > In this animation, I am moving icons around on the screen. I > have two offscreen bitmaps. The first offscreen contains the > background art, which is slow to draw; this way, I only have to > draw it once. I continually CopyBits this whole bitmap into > the second bitmap. I draw the icons the second bitmap, then > copyBits the second bitmap onto the screen. This whole process > happens every event loop. (Slow as this sounds, I have reason > to believe that this is actually not the big time-consumer.) > --Kurisuto > un020070@vaxa.wvnet.edu I'm inclined to believe this is the entire time-consumer (well, not *entire* :)). You obviously have defined a rect for your PlotIcon() routine. Once the icon appears on the screen (your first 'frame' of animation), then it is the only portion of your background which needs replacing (as that is the only portion of the background that was lost from your PlotIcon()). Therefore, keep track of an oldRect. Then rather than CopyBits()ing the whole screen, just replace the background where the icon *was*. I doubt you want flicker, so try this in your loop: plotRect --> oldRect move plotRect to new position UnionRect(plotRect, oldRect, unionOfTwoRect) CopyBits(backgroundOffscreen, intermediateOffscreen, unionOfTwoRect, unionOfTwoRect, srcCopy, nil) set your intermediateOffscreen to be the active port PlotIcon(plotRect, yourIcon) CopyBits(intermediateScreen, onscreenWindow, unionOfTwoRect, unionOfTwoRect, srcCopy, nil); Hows that for a mish-mash of code and algorithm? I made some variable-name assumptions (for clarity I hope). Also, shouldn't really use nil for CopyBits() to the screen (use the visRgn). If you try this out, let me know what speed increase you get. john calhoun
lim@iris.ucdavis.edu (Lloyd Lim) (05/19/91)
In article <1776@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes: >[...] > >In this animation, I am moving icons around on the screen. I >have two offscreen bitmaps. The first offscreen contains the >background art, which is slow to draw; this way, I only have to >draw it once. I continually CopyBits this whole bitmap into >the second bitmap. I draw the icons the second bitmap, then >copyBits the second bitmap onto the screen. This whole process >happens every event loop. (Slow as this sounds, I have reason >to believe that this is actually not the big time-consumer.) But you can still speed it up. Instead of copying the whole background over, keep track of where each icon was and just copy over little squares of the background. You could also take all the old squares, make a region out of them, and use that as the maskRgn in a CopyBits of the whole background. I'm not sure which would be faster. >Each time I plot an icon, I GetIcon it, then draw it using copyBits, >then ReleaseResource it. Now, if I'm not mistaken, this doesn't >actually purge the icon from memory, right? If something else needs >the memory it will write over it, but if nobody needs the memory, >the icon will hang around until the next cycle, and GetIcon will >just give me a handle to the icon in memory, right? IM says: "Given a handle to a resource, ReleaseResource releases the memory occupied by the resource data, if any, and replaces the handle to that resource in the resource map with NIL. The given handle will no longer be recognized as a handle to a resource; if the Resource Manager is subsequently called to get the released resource, a new handle will be allocated. Use this procedure only after you're completely through with a resource." Don't call ReleaseResource. If the resource is purgeable, it will stick around unless the memory is needed for something else. Icons aren't very big so if you're using the same ones over and over, you probably will want to load them once, save the handles, and make them unpurgeable (but not locked). Then just refer to them by the handles. >In doing the calculations for the animation, I frequently refer >to complex data structures by handles. Is this a particularly >slow way of doing things? Could I speed things up appreciably by >locking the handles and using more Pascal WITH statements? There isn't much to a handle dereference. Generally, using handles and keeping them unlocked as much as possible is a good thing to do. If you need to refer to a field with a call that moves memory, make a local copy of the field and use the copy in the call. If you need to use something larger and move memory, HGetState, HLock, and HSetState. WITHs and/or register variables (does Pascal have those?) might help a little. +++ Lloyd Lim Internet: lim@iris.eecs.ucdavis.edu America Online: LimUnltd Compuserve: 72647,660 US Mail: 215 Lysle Leach Hall, U.C. Davis, Davis, CA 95616
keith@Apple.COM (Keith Rollin) (05/19/91)
In article <1776@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes: > >In this animation, I am moving icons around on the screen. I >have two offscreen bitmaps. The first offscreen contains the >background art, which is slow to draw; this way, I only have to >draw it once. I continually CopyBits this whole bitmap into >the second bitmap. I draw the icons the second bitmap, then >copyBits the second bitmap onto the screen. This whole process >happens every event loop. (Slow as this sounds, I have reason >to believe that this is actually not the big time-consumer.) Depending on how many icons you are moving, I can think of two things you could do: - if you have a small number of icons, then don't refresh the entirety of your second buffer. Just overwrite the few icons selectively. That way, you aren't refreshing the majority of your second buffer that doesn't need it. - if you have a large number of icons, then the overhead of calling QuickDraw a large number of times my actaully slow you down enough that a single Copybits call to copy the entire buffer is faster. However, if your buffers are bitmaps with the same dimensions, or PixMaps with the same dimensions and color table information, then try using BlockMove instead of CopyBits. -- ------------------------------------------------------------------------------ Keith Rollin --- Apple Computer, Inc. INTERNET: keith@apple.com UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith "But where the senses fail us, reason must step in." - Galileo
palmer@nntp-server.caltech.edu (David Palmer) (05/19/91)
lim@iris.ucdavis.edu (Lloyd Lim) writes: >In article <1776@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes: >>[...] >> >>In this animation, I am moving icons around on the screen. I >>have two offscreen bitmaps. The first offscreen contains the >>background art, which is slow to draw; this way, I only have to >>draw it once. I continually CopyBits this whole bitmap into >>the second bitmap. I draw the icons the second bitmap, then >>copyBits the second bitmap onto the screen. This whole process >>happens every event loop. (Slow as this sounds, I have reason >>to believe that this is actually not the big time-consumer.) >But you can still speed it up. Instead of copying the whole background >over, keep track of where each icon was and just copy over little squares >of the background. You could also take all the old squares, make a region >out of them, and use that as the maskRgn in a CopyBits of the whole >background. I'm not sure which would be faster. Do an 'InvalRect()' on the place where you remove the icons, and on the new location of the icon. Then when you respond to an 'update' event, just write the background and the icons. This does what you suggested-- only writing to the invalidated regions. The Macintosh Way is to not write anything to the screen except during update events. -- David Palmer palmer@gap.cco.caltech.edu ...rutgers!cit-vax!gap.cco.caltech.edu!palmer "Operator, get me the number for 911" --Homer Simpson
ed@nsx.Berkeley.EDU (Ed Devinney) (05/21/91)
In article <1991May18.231302.16630@nntp-server.caltech.edu>, palmer@nntp-server.caltech.edu (David Palmer) writes: |> Do an 'InvalRect()' on the place where you remove the icons, and on the |> new location of the icon. Then when you respond to an 'update' event, |> just write the background and the icons. This does what you suggested-- |> only writing to the invalidated regions. |> |> The Macintosh Way is to not write anything to the screen except during |> update events. Which is all very nice, but not for animation. Like the commercial says, sometimes you gotta break the rules, and smooth, consistent animation requires taking control of the drawing. (Kind of hard to guarantee a frame rate in a purely user-event-driven environment). |> David Palmer |> palmer@gap.cco.caltech.edu -- ed devinney ed@visix.com Visix Software Inc., Reston, VA ...!uunet!visix!ed "She turned me into a newt!" "A _newt_?" "I got better..."- MP&THG
trebor@lkbreth.foretune.co.jp (Robert J Woodhead) (05/21/91)
ed@nsx.Berkeley.EDU (Ed Devinney) writes: >Which is all very nice, but not for animation. Like the commercial says, sometimes you >gotta break the rules, and smooth, consistent animation requires taking control of the >drawing. (Kind of hard to guarantee a frame rate in a purely user-event-driven >environment). Well said! I've been doing a little hacking with a colorspace II board recently and worked out a couple of simple techniques that can be useful. My problem was to be able to do an instantaneous (eg: during the VBL time) change from 1 image to another. Unfortunately, a Mac II can't repaint all 250k odd pixels in <1/60th of a second! (BTW, if anyone has any tricks to speed up block transfers to NuBus device memory, I'd be interested!) Since I often needed to change most of the pixels on the screen, but DIDN'T need to do this each and every VBL interrupt, the following technique was useful. The idea is to reduce the number of simultaneous colors you can have on the screen and trade this for having multiple images in the screen buffer. You then simply change the color table in order to make the desired image appear. A simple example: Lets say you only need 8 colors per image (3 bits per "pixel". You reserve a block of color table entries that start on an 64 entry boundary. You need 64 of them (6 bits) do be able to put 2 8 color images into the buffer at the same time. These colors will all be in the format of, say, 01AAABBB, where AAA is one set of 3 pixels and BBB is another set. Next, paint image #1 into the AAA pixels and image #2 into the BBB pixels. Now set up 2 color tables for the graphics device. In one, the AAA bits are "don't care", so that the color setting for any value in the table depends only on the value of BBB. The second is the inverse, where the AAA bits are don't care bits. In each table, each color is repeated 8 times. Now, by flipping from color table to color table in a slotVBL routine, the images will appear alternately. If the object you are animating is small enough, you have enough time to repaint the invisible object before the next VBL time, and thus do totally seamless animation (albeit in reduced colors). Note that you can change the invisible object at any time, because changes to those bits don't affect the visible image on the screen. In my own application (a video titler) I only needed 4 colors, so I have 3 different objects on the screen, and a pixel format of 01AABBCC. Thus my program has 1 image visible, one waiting to be displayed, and one being created. You can also, by use of multiple color tables, do fades and dissolves between images. Not a general technique, but for some things it is incredibly useful. -- +--------------------------------------------------------------------------+ | Robert J. Woodhead, Biar Games / AnimEigo, Incs. trebor@foretune.co.jp | | "The Force. It surrounds us; It enfolds us; It gets us dates on Saturday | | Nights." -- Obi Wan Kenobi, Famous Jedi Knight and Party Animal. |
jimc@isc-br.ISC-BR.COM (Jim Cathey) (05/22/91)
In article <1991May18.231302.16630@nntp-server.caltech.edu> palmer@nntp-server.caltech.edu (David Palmer) writes: >Do an 'InvalRect()' on the place where you remove the icons, and on the >new location of the icon. Then when you respond to an 'update' event, >just write the background and the icons. This does what you suggested-- >only writing to the invalidated regions. Yuck. Sort of like writing yourself a note to buy eggs on Friday, and then putting a stamp on it and your own address and dropping it into the mailbox instead of leaving it on the refrigerator! If you know you need to draw the icons, then just draw the icons. Why invoke a whole bunch of region math when you don't need to, especially when it's just going to tell you what you already knew? It will certainly be slower. >The Macintosh Way is to not write anything to the screen except during >update events. I disagree. The Way is to write on the screen whenever necessary (though it's not necessary more often than once per VSYNC time per item) _and_ to write (everything dirty) on the screen during update events --- not 'instead of'. The same goes for a lot of GUI systems. +----------------+ ! II CCCCCC ! Jim Cathey ! II SSSSCC ! ISC-Bunker Ramo ! II CC ! TAF-C8; Spokane, WA 99220 ! IISSSS CC ! UUCP: uunet!isc-br!jimc (jimc@isc-br.isc-br.com) ! II CCCCCC ! (509) 927-5757 +----------------+ "With excitement like this, who is needing enemas?"