Avoid flickering with double buffering on Symbian
| ID | Creation date | June 13, 2008 | |
| Platform | S60 3rd Edition, MR | Tested on devices | Nokia N95 |
| Category | Symbian C++ | Subcategory | Code Examples |
| Keywords (APIs, classes, methods, functions): double buffering, CFbsBitmapDevice, CFbsBitGc, CFbsBitmap |
Overview
When drawing images directly on the screen and there exists some animation can screen flicker. A common technique to solve this is to draw images on an off-screen buffer, and them copy its contents to the screen when the drawing operations are finished.
Following example shows how to implement this technique. There is neede two buffers, hence the term "double buffering". This off-screen buffer has the same dimensions of the screen than the original one.
MMP file
The following capabilities and libraries are required:
CAPABILITY NONE
LIBRARY fbscli.lib
LIBRARY bitgdi.lib
Header
Here is example header of CCoeControl componet where double buffering is enabled
#include <coecntrl.h>
#include <bitstd.h>
#include <bitdev.h>
class CMyContainer : public CCoeControl
{
public:
void NewL(const TRect& aRect)
void ConstructL(const TRect& aRect);
virtual ~CImageConverterContainer();
private:
void CMyContainer();
void SizeChanged();
void HandleResourceChange(TInt aType);
TInt CountComponentControls() const;
CCoeControl* ComponentControl(TInt aIndex) const;
void Draw(const TRect& aRect) const;
// for Double buffering
public:
void DrawToBackBuffer();
// for Double buffering
private:
void CreateBackBufferL();
void ReleaseBackBuffer();
// for Double buffering
private:
CFbsBitmap* iBackBuffer;
CFbsBitmapDevice* iBackBufferDevice;
CFbsBitGc* iBackBufferContext;
TSize iBackBufferSize;
// class other member variables if needed
private:
};
Source
There is source code only double buffering-related data
void CMyContainer::SizeChanged()
{
// Delete back buffer and create a new one with new size
ReleaseBackBuffer();
CreateBackBufferL();
DrawToBackBuffer();
}
void CMyContainer::CreateBackBufferL()
{
// Create back buffer bitmap
iBackBuffer = new (ELeave) CFbsBitmap;
User::LeaveIfError( iBackBuffer->Create(Size(),
iEikonEnv->DefaultDisplayMode()));
// Create back buffer graphics context
iBackBufferDevice = CFbsBitmapDevice::NewL(iBackBuffer);
User::LeaveIfError(iBackBufferDevice->CreateContext(iBackBufferContext));
iBackBufferContext->SetPenStyle(CGraphicsContext::ESolidPen);
iBackBufferSize = iBackBuffer->SizeInPixels();
}
void CMyContainer::ReleaseBackBuffer()
{
// Release double buffering classes
if (iBackBufferContext)
{
delete iBackBufferContext;
iBackBufferContext = NULL;
}
if (iBackBufferDevice)
{
delete iBackBufferDevice;
iBackBufferDevice = NULL;
}
if (iBackBuffer)
{
delete iBackBuffer;
iBackBuffer = NULL;
}
iBackBufferSize = TSize(0, 0);
}
void CMyContainer::DrawToBackBuffer()
{
if (!iBackBufferContext)
{
return;
}
iBackBufferContext->Clear();
// TODO: do your drawing there.
// Remember to draw to iBackBufferContext buffered graphic contex
// Example of drawing bitmap into iBackBufferContext
//if(iBitmap)
// {
// iBackBufferContext->BitBlt( iPicturePoint, iBitmap );
// }
}
void CMyContainer::Draw(const TRect& aRect) const
{
CWindowGc& gc = SystemGc();
// Copy backbuffer into the screen
gc.BitBlt(TPoint(0, 0), iBackBuffer);
// TODO: Remove your all drawing from there to DrawToBackBuffer
}
CMyContainer::~CMyContainer()
{
ReleaseBackBuffer();
}
Using
Old way was
iAppContainer->DrawNow();
and now with double buffering
iAppContainer->DrawToBackBuffer();
iAppContainer->DrawNow();
Postconditions
No anymore flickering

