При рисовании на экран с использованием сервера окна требуется переключить контекст, что замедляет рисование. Увеличить скорость рисования можно, отказавшись от использования сервера окна и получив прямой доступ к экрану. Эту технику будем называтьпрямым рисованием (Direct Draw).


Symbian OS позволяет реализовать прямое рисование тремя способами:

  • Создание и использование CfbsScreenDevice.
  • Прямой доступ к памяти экрана.
  • Использование CdirectScreenAccess.

Использование CfbsScreenDevice для прямого рисования

CFbsScreenDevice представляет собой графическое устройство, которое может посылать информацию драйверу экрана SCDV.DLL. После создания CFbsBitGc графического контекста, с ним можно работать как с любым графическим устройством. Однако, рисование происходит напрямую без использования сервера окна.

Прямой доступ к видеопамяти

Самым быстрым способом рисования является прямой доступ к видеопамяти:

void CMyGameView::FillScreenDirectly()const
{
TPckgBuf<tscreeninfov01> infoPckg;
TScreenInfoV01&amp; screenInfo= infoPckg();
UserSvr::ScreenInfo(infoPckg);
TUint16* screenMemory=(TUint16*) screenInfo.iScreenAddress+16;
for(TInt y=0; y< screenInfo.iScreenSize.iHeight; y++)
{
for(TInt x=0; x< screenInfo.iScreenSize.iWidth; x++)
{
*screenMemory++=0;
}
}
}</tscreeninfov01>

В памяти экрана расположен 32-байтный заголовок, который нужно принимать во внимание при работе.

Рисование в память напрямую происходит быстрее, чем через CFbsScreenDevice, но доступные программисту функциональные возможности зависят от модели устройства. Например, в одних телефонах содержание экрана обновляется автоматически при изменении памяти, в других - требуется принудительное обновление.

При использовании прямого доступа к памяти Вы не сможете запустить программу на эмуляторе. Тестирование необходимо проводить на целевом устройстве. Конечно, Вы можете решить эту проблему, используя вспомогательное изображение. При запуске на эмуляторе работайте с адресным пространством изображения, а при запуске на устройстве - с видеопамятью.

void CMyGameView::MyDrawing()
{
#ifdef __WINS__
// Работаем с рисунком
TUint16* myScreenPointer= iMyBitmap.DataAddress();
#else // Аппаратная среда
// Работаем с видеопамятью
TUint16* myScreenPointer= GetMyScreenAddress();
#endif
 DoMyDrawing(myScreenPointer);
}

Использование CDirectScreenAccess для быстрого рисования

Общей проблемой для методов прямого рисования является то, что сервер окна не знает о рисовании, поэтому он не может послать приложению уведомление о том, что оно потеряло фокус и другое окно выдвинуто на передний план. Не смотря на то, что приложение получит сообщение о потери фокуса, Вы не сможете достаточно быстро остановить прямое рисование, и экран окажется "загрязнен". Это может, например, произойти, если во время работы приложения получен входящий звонок, и приложение телефона выходит на передний план.

Symbian OS предлагает использовать CDirectScreenAccess. Он более безопасен и лишен описанных недостатков, но все еще достаточно быстр. CDirectScreenAccess поддерживает связь с сервером окна с помощью двух уведомлений:

  • MDirectScreenAccess::AbortNow: Вызывается, когда прямой доступ к экрану должен быть прекращен, например, когда необходимо отобразить окно всплывающего диалога.
  • MDirectScreenAccess::Restart: Вызывается, когда прямое рисование может быть возобновлено.

Ниже приведен пример, иллюстрирующий работу через CDirectScreenAccess.

// Унаследован от MDirectScreenAccess
void CMyGameView::Restart(RDirectScreenAccess::TTerminationReasons aReason)
{
// Обычно просто перезапускается прямой доступ к экрану
TRAPD(err, iMyDrawer->StartL());
if(err!= KErrNone)
{
// Ошибка при перезапуске
}
}
 
// Унаследован от MDirectScreenAccess; вызывается, когда необходимо
// немедленно запретить прямой доступ
void CMyGameView::AbortNow(RDirectScreenAccess::TTerminationReasons aReason)
{
// Немедленное запрещение доступа к видеопамяти
// то есть диалог становится видимым.
}
 
// Строим CDirectScreenAccess
void CHelloWorldBasicAppView::CreateMyDrawerL()
{
delete iMyDrawer;
iMyDrawer=NULL;
iMyDrawer= CDirectScreenAccess::NewL( iEikonEnv->WsSession(),
*iEikonEnv->ScreenDevice(), Window(),*this);
iEikonEnv->WsSession().Flush();
iMyDrawer->StartL();
iMyDrawer->ScreenDevice()->SetAutoUpdate(ETrue);
}
 
// Копируем внеэкранный буфер на экран, используя CDirectScreenAccess
void CMyGameView::DisplayBackBuffer()const
{
iMyDrawer->Gc()->BitBlt( TPoint(0,0), iMyBackBuffer);
}

Перед тем как вызывать CDirectScreenAccess::StartL для активизации прямого рисования, буфер клиента сервера окна должен быть очищен. Для того чтобы разрешить автоматическое обновление экрана, нужно вызвать метод устройства экрана SetAutoUpdate с параметром ETrue. После активации поддержки прямого рисования CDirectScreenAccess создает CFbsBitGc графический контекст, который можно использовать для рисования на экране.

Когда другое окно пытается пробиться на передний план, CDirectScreenAccess получает сообщение от сервера о необходимости запрета рисование в видеопамять. CDirectScreenAccess вызывает метод AbortNow полученного класса MDirectScreenAccess, который запрещает доступ к видеопамяти. Чтобы избежать эффекта "загрязнения" экрана, сервер окна не производит рисования, пока не получит подтверждение о прекращении доступа к видеопамяти.


Перевод:aRix




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна