Открыть главное меню

AHI: различия между версиями

(Даже немножечко, чайная ложечка - это уже хорошо!)
м (Контекст устройства)
Строка 48:Строка 48:
 
dCtx = DAL_GetDeviceContext(0);
 
dCtx = DAL_GetDeviceContext(0);
 
</pre>
 
</pre>
Недостаток этого способа - необходимо помнить, что приложение не является единственным клиентом драйвера, и делать необходимые установки перед каждой операцией вывода.
+
Недостаток этого способа - необходимо помнить, что приложение не является единственным клиентом драйвера, и делать необходимые установки перед каждой операцией вывода. А так же есть вероятность появления искажений в прорисовке экрана самой системой (UIS).
 
</li>
 
</li>
 
<li>Либо можно создать новый контекст только для нужд приложения, с помощью функций [[ldrGetAhiDevice]] и [[AhiDevOpen]]:
 
<li>Либо можно создать новый контекст только для нужд приложения, с помощью функций [[ldrGetAhiDevice]] и [[AhiDevOpen]]:

Версия 08:42, 22 августа 2009

AHI англ. ATI Handheld Interface — драйвер для чипов ATI. Присутствует в каждой прошивке для телефонов, где есть чип ATI, а это - все телефоны на базе LTE и LTE2.

Чипы ATI

Два основных чипа, используемых в телефонах Motorola:

  • ATI W2250 - преимущественно в LTE
  • ATI W2260 - преимущественно в LTE2

API драйвера для различных чипов одинаков, однако внутреннее устройство значительно различается (По словам владельцев. Лично мне неизвестно, насколько. A51)

Применение

Вывод графики через драйвер, в обход стандартных средств прошивки (см. Canvas), предоставляет больше возможностей по сравнению с последними, и, при правильном применении, работает значительно быстрее.

Если Вам нужно, чтобы вывод собственной графики был на максимально возможной скорости, как, например, для разработки динамичных игр - тогда стоит задуматься о применении средств драйвера. В остальных случаях использование Canvas будет значительно проще.

С учётом сказанного, для наиболее эффективного использования средств, предоставляемых драйвером, их следует использовать в приложении, основанном на таске.

Основные понятия и начало работы

API драйвера напоминает интерфейсом обычные графические библиотеки, как например GDI. Рассмотрим основные понятия и приёмы работы с AHI в применении к эльфописанию.

AHI разрабатывался отдельно от программных продуктов, где он используется, поэтому был спроектирован максимально универсальным. Одно из следствий такой универсальности является возможность драйвера распараллеливать работу с железом между различными "клиентами", а именно - между приложениями операционной системы и самой ОС.

Для обеспечения такой возможности используется специальный объект, с которым разработчику эльфа под драйвер придётся сталкиваться постоянно - это контекст устройства.

Контекст устройства

Контекст устройства (англ. Device Context) — структура данных, обеспечивающая эксклюзивный доступ к устройству вывода для приложения, использующего эту структуру и предотвращающая влияние других приложений на процесс работы с устройством. В ней хранятся все данные о текущем состоянии устройства, устанавливаемом приложением - владельцем контекста.

Чтобы лучше разъяснить как это работает, рассмотрим ситуацию на упрощенном примере:

Приложения A и B работают параллельно, и хотят получить доступ к Устройству, для чего каждый из них создаёт с помощью AHI новый контекст для собственного пользования.
Приложение A пытается изменить состояние Устройства, скажем, меняет основной цвет "кисти" на красный. А на самом деле, информация о цвете кисти попадает не сразу в Устройство, а сохраняется в контексте приложения A.
Приложение B тоже меняет (в своём контексте) цвет кисти, но на синий.
Теперь, Приложение B пытается вывести линию синим цветом. Для этого драйвер отсылает контекст приложения B (вместе с информацией о цвете) Устройству и подаёт команду на рисование линии текущим (синим) цветом.
После этого, если Приложение A тоже решит нарисовать линию, ему не придётся "задумываться" о том, что Приложение B что-то там проделало с Устройством, а просто вызовет функцию рисования линии, и драйвер нарисует её красным цветом, выполнив те же процедуры с контекстом.

Если бы небыло системы контекстов, и данные сразу попадали в устройство, то после установки Приложением B цвета в синий, Приложение A тоже бы получало синие линии вместо желаемых красных.


В коде контекст описывается как тип AHIDEVCONTEXT_T и является первым параметром почти у всех функций AHI. В ОС P2K напрямую функции драйвера не используются (кроме Java-машины), а Функции графики предоставляются через промежуточную надстройку над AHI - DAL, поэтому все приложения ОС (а точнее, система UIS), так же как и сама ОС, используют единственный системный контекст.

Для эльфов есть выбор, как получить контекст:

  1. Можно получить системный контекст, который использует ОС, с помощью функции DAL_GetDeviceContext:
    // Это будет наш контекст. Удобнее всего объявить его глобальным
    AHIDEVCONTEXT_T	dCtx;
    // Получаем системный контекст
    dCtx = DAL_GetDeviceContext(0);

    Недостаток этого способа - необходимо помнить, что приложение не является единственным клиентом драйвера, и делать необходимые установки перед каждой операцией вывода. А так же есть вероятность появления искажений в прорисовке экрана самой системой (UIS).

  2. Либо можно создать новый контекст только для нужд приложения, с помощью функций ldrGetAhiDevice и AhiDevOpen:
    // Это будет наш контекст. Удобнее всего объявить его глобальным
    AHIDEVCONTEXT_T	dCtx;
    // Информация об устройстве
    AHIDEVICE_T	device;
    // В EP2 уже есть вспомогательная функция для получения информации об устройстве
    device = ldrGetAhiDevice();
    // Создаём контекст
    sts = AhiDevOpen( &dCtx, device, "Matrix", 0 );

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

Поверхности

Прежде чем переходить к рассмотрению непосредственно программирования под AHI, необходимо ознакомиться с ещё одним важнейшим понятием - "поверхностями".

Поверхность (англ. Surface, "Сурфейс") — логически выделенный участок видеопамяти чипа ATI.

Как многим из вас известно, у видеочипов часто есть собственная видеопамять, причём эта видеопамять не обязательно доступна процессору напрмяую. В телефонах Motorola с чипами ATI именно такой случай.

Размер внутренней видеопамяти (располагается прямо на чипе) на W2250 и W2260 одинаков и составляет 192Kb, однако к W2260 подключен внешний модуль для расширения внутренней видеопамяти. Последняя работает медленнее внутренней, что отчасти компенсируется её значительно большим объёмом.

MCU может обращаться к видеопамяти двумя способами - через DMAC (только запись), либо через QSPI (чтение и запись).

Все растровые операции AHI производятся с участием поверхностей. Есть четыре наиболее важные поверхности, используемые в работе драйвера. Однако, последняя фраза не означает, что поверхностей именно четыре, скорее следует понимать это как статусы, присваиваемые определённым поверхностям, и при этом одна и та же поверхность(участок памяти) может принимать одновременно несколько таких статусов:

  • Отображаемая поверхность ("Display Surface", "Экранная поверхность", она же "Экранный буфер")
    Это та поверхность, из которой в данный момент чип берёт информацию для непосредственного вывода на экран.
    Устанавливается с помощью функции AhiDispSurfSet, а получить можно с помощью AhiDispSurfGet
  • Поверхность назначения ("Destination Surface", "Поверхность-приёмник")
    Эта поверхность является целевой для функций рисования, тоесть в неё будет попадать результат операции.
    Устанавливается функцией AhiDrawSurfDstSet
  • Поверхность-источник ("Source Surface")
    Эта поверхность является источником данных для функций рисования, например картинка спрайта, который мы хотим нарисовать.
    Устанавливается функцией AhiDrawSurfSrcSet
  • Поверхность кисти ("Brush Surface")
    С этой поверхностью приложения никогда не работают напрямую, но о её существовании лучше знать, чтобы проще было понимать принцип работы некоторых функций рисования - она является важным вспомогательным инструментом. Всегда монохромная (однобитная).
    Устанавливается самим драйвером, а настраивается с помощью функции AhiDrawBrushSet.


Инициализация

Итак, у нас теперь есть контекст, полученный одним из двух способов, указанных выше. Что дальше?

Вне зависимости от того, собственный у нас контекст или нет, нужно провести его инициализацию. Различие лишь в том, что в случае собственного контекста её достаточно провести один раз, а в случае использования системного - почти каждый раз перед вызовом какой-либо функции рисования AHI.

Перед тем, как вызвать какую-либо функцию рисования, мы должны установить необходимые для её работы параметры:

  1. Установить поверхность-приёмник
    Часто для этого используется отображаемая поверхность, если не планируется вывод с использованием двойной буферизации.
    // Наш контекст, полученный ранее
    AHIDEVCONTEXT_T	dCtx;
    // Наша отображаемая поверхность
    AHISURFACE_T	sDisp;
    // Получим отображаемую поверхность. Достаточно сделать это один раз, ведь врядли она поменяется.
    AhiDispSurfGet( dCtx, &sDisp );
    // Устанавливаем поверхность-приёмник
    AhiDrawSurfDstSet( dCtx, sDisp, 0 );
  2. Установить поверхность-источник
    Обычно для этой роли используют либо пользовательскую поверхность с нужной к выводу картинкой, либо системную внеэкранную поверхность (см. Двойная буферизация).
    // Сохраним сюда системную внеэкранную поверхность
    AHISURFACE_T	sDraw;
    // Получим системную внеэкранную поверхность
    sDraw = DAL_GetDrawingSurface( DISPLAY_MAIN );
    // Устанавливаем поверхность-источник
    AhiDrawSurfSrcSet( dCtx, sDraw, 0 );
  3. Установить области вырезания для приёмника и источника
    Пока что выключим их, и для этого передадим в функции AhiDrawClipDstSet и AhiDrawClipSrcSet - NULL:
    // Выключаем области вырезания для приёмника и источника
    AhiDrawClipDstSet( dCtx, NULL );
    AhiDrawClipSrcSet( dCtx, NULL );
  4. Установить растровую операцию
    Чтобы не углубляться в рамках этой статьи в растровые операции, ограничимся пока что простым правилом: Для вывода растровых изображений устанавливаем AHIROP_SRCCOPY, а для рисования цветом - AHIROP_PATTERN. Отсановимся на последнем, так как пригодится в последующем примере.
    // Устанавливаем растровую операцию на применение кисти
    AhiDrawRopSet( dCtx, AHIROP3(AHIROP_PATTERN) );
  5. Настроить кисть
    Это делать не обязательно, если мы не собираемся рисовать графические примитивы. Но так как мы собираемся, то...
    // Установим кисть на самую обычную, сплошную (SOLID)
    AhiDrawBrushSet(devCx, NULL, NULL, 0x0, AHIFLAG_BRUSH_SOLID);

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

Проба пера

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

Для первого раза нарисуем цветной графический примитив.

// Вспомогательная переменная для указания области экрана
AHIRECT_T	rect;
// Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы
// Составить 16-битное значение цвета нам поможет макрос ATI_565RGB.
// Параметрами являются значения трёх компонент цвета RGB в пределах 0-255.
AhiDrawBrushFgColorSet(devCx, ATI_565RGB(0,0,255)); // Ярко-синий
// Зададим прямоугольник на экране, который будет залит нашим цветом
// x1, y1 - координаты левого верхнего угла прямоугольника, x2, y2 - правого нижнего.
rect.x1 = 0;
rect.y1 = 0;
rect.x2 = 64;
rect.y2 = 64;
// Нарисуем прямоугольник rect
AhiDrawSpans( dCtx, &rect, 1, 0);

References: AhiDrawBrushFgColorSet, AhiDrawSpans

После этого мы получим на экране синий квадрат в левом верхнем углу.



Пока что это всё, ждите продолжения :) --Andy51 23:42, 20 августа 2009 (MSD)