[haiku-development] Re: Blitting

  • From: Stephan Aßmus <superstippi@xxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Tue, 15 Sep 2009 10:56:07 +0200

Caitlin Shaw schrieb:
> I'm wondering what kind of support does Haiku offer for what's commonly 
> called "bit-block-transfer" or "copybits" (within normal applications, 
> not talking about the Game Kit).
> 
> I've managed to:
> 
> * Implement an off-screen buffer by creating a BBitmap and associating 
> it with a BView, then blitting the buffer to the screen by calling 
> DrawBitmap on the target BView, and,
> 
> * Move data around within a single BView by calling it's CopyBits function.
> 
> Am I missing something? Am I thinking using the wrong methodology? But 
> these methods seem to missing some important flexibility, namely, it 
> doesn't seem to offer any way to blit OUT of a BView, only IN, and then 
> there's special rules about where the source data can come from.
> 
> It seems that surely there would be some function which takes two BViews 
> and copies between them. The existing methods (that I know of) just seem 
> kind of uncomfortable and inflexible. Is there a way to have a 
> BBitmap-enabled BView, which is also visible onscreen? And, is 
> "DrawBitmap" the recommended way to perform blits (is it optimized for 
> speed in the same way that a bit-blit-specific function would be on 
> other systems).
> 
> BTW, the application for this is that I have an on-screen image, which 
> has a user-movable cursor in it. The cursor was supposed to have a 
> backbuffer, which would contain the contents of the screen behind it, so 
> that the screen could be restored when the cursor is moved. The only way 
> I have found to implement this technique on Haiku is to backbuffer the 
> entire screen, but that means that instead of two teensy tiny blits I 
> have to do one HUGE blit every time the screen is updated, which is very 
> inefficient; so instead, I have taken to simply recalculating the 
> missing image data, but that is also fairly inefficient.

The CopyBits() routine used to be hardware accelerated. On Haiku, it is 
currently not, you would have to build your own image to enable it. 
Since it's potentially hardware accelerated, it cannot take a source 
rectangle outside of the screen.

What you want to accomplish is done via DrawBitmap(). You just need to 
keep different BBitmaps around for the various layers of your drawings. 
One bitmap would be the background, of the size of your view, the other 
would be the cursor, of the size of just the cursor. When you want to 
redraw the cursor, it would work like this:

BRect originalCursorRectInViewCoordinates = ...;
BRect newCursorRect
   = originalCursorRectInViewCoordinates.OffsetByCopy(cursorOffset);
Invalidate(originalCursorRectInViewCoordinates | newCursorRect);

// done for now, your Draw() hook will be called asynchonously

In your Draw() hook:

DrawBitmap(backgroundBitmap);
DrawBitmap(cursorBitmap, newCursorRect.LeftTop())

And that will work without any flickering, since the Haiku rendering is 
double buffered. It will first draw the background, which will be 
automatically clipped to the update part (since you called Invalidate() 
on just that part), and then the cursor bitmap on top of it. After your 
Draw() routine is completely finished, it will blit the area which 
changed to the screen.

Best regards,
-Stephan

Other related posts: