AHI: различия между версиями
Tim apple (обсуждение | вклад) м (→Контекст устройства) | Andy51 (обсуждение | вклад) (Добавил разделы про координаты и цвет) | ||
Строка 93: | Строка 93: | ||
*:Устанавливается самим драйвером, а настраивается с помощью функции [[AhiDrawBrushSet]]. | *:Устанавливается самим драйвером, а настраивается с помощью функции [[AhiDrawBrushSet]]. | ||
+ | === Координаты === | ||
+ | Ещё одна вещь, с которой придётся постоянно иметь дело - это точки и области экрана и их координаты. | ||
+ | |||
+ | Координатная система экрана (да и всякой поверхности, тоже!) с точки зрения чипа ATI имеет следующую конфигурацию: | ||
+ | *Начало отсчёта - в левом верхнем углу, отсчёт начинается с нуля | ||
+ | *Ось X направлена вправо | ||
+ | *Ось Y направлена вниз | ||
+ | |||
+ | Два основных объекта для описания координатных положений - это <tt>AHIPOINT_T<tt/> и <tt>AHIRECT_T</tt>: | ||
+ | <pre> | ||
+ | typedef struct | ||
+ | { | ||
+ | INT32 x, y; | ||
+ | |||
+ | } AHIPOINT_T; | ||
+ | |||
+ | typedef struct | ||
+ | { | ||
+ | INT32 x1, y1, x2, y2; | ||
+ | |||
+ | } AHIRECT_T; | ||
+ | </pre> | ||
+ | |||
+ | Если с первым всё понятно - просто задаёт координаты точки по x и y, то <tt>AHIRECT_T</tt>, который задаёт прямоугольную область экрана, стоит рассмотреть чуть подробнее: | ||
+ | *<tt>x1, y1</tt> - координаты левого верхнего угла прямоугольника | ||
+ | *<tt>x2, y2</tt> - правого нижнего | ||
+ | Важное замечание: в отличие от используемой в [[UIS]] системе задания такой области, здесь координаты правого нижнего угла задаются '''не включительно'''! | ||
+ | Например, если x1 = 0, x2 = 32 - это означает, что в область попадут точки с координатами x от 0 до 31. | ||
+ | |||
+ | |||
+ | Чаще всего эти две структуры используются в функциях AHI примерно так: | ||
+ | <pre> | ||
+ | UINT32 AhiDrawBitBlt( AHIDEVCONTEXT_T devCx, AHIRECT_T *dstRect, AHIPOINT_T *srcPt ); | ||
+ | </pre> | ||
+ | *<tt>AHIRECT_T</tt> указывает область на целевой поверхности, куда попадёт картинка из поверхности-источника, и именно он задаёт размер картинки. | ||
+ | *<tt>AHIPOINT_T</tt> указывает координаты левого верхнего угла на поверхности-источнике, откуда будет скопирована область, размерами равная размерам прямоугольника <tt>AHIRECT_T</tt>. | ||
+ | |||
+ | === Цвет === | ||
+ | Как многие знают, во многих телефонах используются дисплеи с глубиной цвета 16 бит (Покомпонентно: 5 бит на красный, 6 бит на зелёный и 5 - на синий, "RGB565"), а в настольных компьютерах - с глубиной цвета в 24 бита (по 8 бит на каждую компоненту цвета, "RGB888"). Многие привыкли к заданию цвета в 24-битном формате на настольных компьютерах, да и это намного легче, стоит только рассмотреть пример: 0xFACE8D - в 24bpp сразу видно, какая интенсивность цвета на каждой компоненте, а на 16bpp это будет 0xFE71, и ничего не понятно... Вебдизайнеры поймут. | ||
+ | |||
+ | Для облегчения задачи, предусмотрен макрос, который получает из привычного RGB888 цвета - RGB565, например: | ||
+ | <pre> | ||
+ | ATI_565RGB(0xFA, 0xCE, 0x8D); | ||
+ | </pre> | ||
+ | Конечно, пользоваться им необязательно для случаев "чёрного" и "белого" - это 0x0 и 0xFFFF соответственно. | ||
+ | {{Внимание|Нетрудно однако подсчитать, что "белый"(0xFFFF) в RGB565 при переводе обратно в RGB888 будет уже не очень "белым", далеко не 0xFFFFFF. Это полезно иметь в виду, когда работаете с картинками в формате RGB565}} | ||
+ | |||
+ | Возможно, у Вас уже назрел вопрос ещё с первых строк этого раздела, "А как же 18-битные дисплеи, которые ставили, например, на E1?" | ||
+ | |||
+ | Так вот по крайней мере [[W2250]] не имеет поддержки 18-битных поверхностей, чтобы обеспечить использование возможностей такого дисплея, так что это был не более чем маркетинговый ход. Впрочем, это же судя по всему касается и [[LTE2]] телефонов, так как для графики там опять же используются 16-битные поверхности. | ||
=== Инициализация === | === Инициализация === | ||
Строка 173: | Строка 223: | ||
// Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы | // Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы | ||
− | |||
− | |||
AhiDrawBrushFgColorSet(devCx, ATI_565RGB(0,0,255)); // Ярко-синий | AhiDrawBrushFgColorSet(devCx, ATI_565RGB(0,0,255)); // Ярко-синий | ||
// Зададим прямоугольник на экране, который будет залит нашим цветом | // Зададим прямоугольник на экране, который будет залит нашим цветом | ||
− | |||
rect.x1 = 0; | rect.x1 = 0; | ||
rect.y1 = 0; | rect.y1 = 0; |
Версия 18:18, 22 августа 2009
AHI англ. ATI Handheld Interface — драйвер для чипов ATI. Присутствует в каждой прошивке для телефонов, где есть чип ATI, а это - все телефоны на базе LTE и LTE2.
Содержание
Чипы ATI
Два основных чипа, используемых в телефонах Motorola:
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), так же как и сама ОС, используют единственный системный контекст.
Для эльфов есть выбор, как получить контекст:
- Можно получить системный контекст, который использует ОС, с помощью функции DAL_GetDeviceContext:
// Это будет наш контекст. Удобнее всего объявить его глобальным AHIDEVCONTEXT_T dCtx; // Получаем системный контекст dCtx = DAL_GetDeviceContext(0);
Недостаток этого способа - необходимо помнить, что приложение не является единственным клиентом драйвера, и делать необходимые установки перед каждой операцией вывода. А так же есть вероятность появления искажений в прорисовке экрана самой системой (UIS).
- Либо можно создать новый контекст только для нужд приложения, с помощью функций 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.
Координаты
Ещё одна вещь, с которой придётся постоянно иметь дело - это точки и области экрана и их координаты.
Координатная система экрана (да и всякой поверхности, тоже!) с точки зрения чипа ATI имеет следующую конфигурацию:
- Начало отсчёта - в левом верхнем углу, отсчёт начинается с нуля
- Ось X направлена вправо
- Ось Y направлена вниз
Два основных объекта для описания координатных положений - это AHIPOINT_T и AHIRECT_T:
typedef struct { INT32 x, y; } AHIPOINT_T; typedef struct { INT32 x1, y1, x2, y2; } AHIRECT_T;
Если с первым всё понятно - просто задаёт координаты точки по x и y, то AHIRECT_T, который задаёт прямоугольную область экрана, стоит рассмотреть чуть подробнее:
- x1, y1 - координаты левого верхнего угла прямоугольника
- x2, y2 - правого нижнего
Важное замечание: в отличие от используемой в UIS системе задания такой области, здесь координаты правого нижнего угла задаются не включительно! Например, если x1 = 0, x2 = 32 - это означает, что в область попадут точки с координатами x от 0 до 31.
Чаще всего эти две структуры используются в функциях AHI примерно так:
UINT32 AhiDrawBitBlt( AHIDEVCONTEXT_T devCx, AHIRECT_T *dstRect, AHIPOINT_T *srcPt );
- AHIRECT_T указывает область на целевой поверхности, куда попадёт картинка из поверхности-источника, и именно он задаёт размер картинки.
- AHIPOINT_T указывает координаты левого верхнего угла на поверхности-источнике, откуда будет скопирована область, размерами равная размерам прямоугольника AHIRECT_T.
Цвет
Как многие знают, во многих телефонах используются дисплеи с глубиной цвета 16 бит (Покомпонентно: 5 бит на красный, 6 бит на зелёный и 5 - на синий, "RGB565"), а в настольных компьютерах - с глубиной цвета в 24 бита (по 8 бит на каждую компоненту цвета, "RGB888"). Многие привыкли к заданию цвета в 24-битном формате на настольных компьютерах, да и это намного легче, стоит только рассмотреть пример: 0xFACE8D - в 24bpp сразу видно, какая интенсивность цвета на каждой компоненте, а на 16bpp это будет 0xFE71, и ничего не понятно... Вебдизайнеры поймут.
Для облегчения задачи, предусмотрен макрос, который получает из привычного RGB888 цвета - RGB565, например:
ATI_565RGB(0xFA, 0xCE, 0x8D);
Конечно, пользоваться им необязательно для случаев "чёрного" и "белого" - это 0x0 и 0xFFFF соответственно.
Нетрудно однако подсчитать, что "белый"(0xFFFF) в RGB565 при переводе обратно в RGB888 будет уже не очень "белым", далеко не 0xFFFFFF. Это полезно иметь в виду, когда работаете с картинками в формате RGB565
Возможно, у Вас уже назрел вопрос ещё с первых строк этого раздела, "А как же 18-битные дисплеи, которые ставили, например, на E1?"
Так вот по крайней мере W2250 не имеет поддержки 18-битных поверхностей, чтобы обеспечить использование возможностей такого дисплея, так что это был не более чем маркетинговый ход. Впрочем, это же судя по всему касается и LTE2 телефонов, так как для графики там опять же используются 16-битные поверхности.
Инициализация
Итак, у нас теперь есть контекст, полученный одним из двух способов, указанных выше. Что дальше?
Вне зависимости от того, собственный у нас контекст или нет, нужно провести его инициализацию. Различие лишь в том, что в случае собственного контекста её достаточно провести один раз, а в случае использования системного - почти каждый раз перед вызовом какой-либо функции рисования AHI.
Перед тем, как вызвать какую-либо функцию рисования, мы должны установить необходимые для её работы параметры:
- Установить поверхность-приёмник
Часто для этого используется отображаемая поверхность, если не планируется вывод с использованием двойной буферизации.// Наш контекст, полученный ранее AHIDEVCONTEXT_T dCtx; // Наша отображаемая поверхность AHISURFACE_T sDisp; // Получим отображаемую поверхность. Достаточно сделать это один раз, ведь врядли она поменяется. AhiDispSurfGet( dCtx, &sDisp ); // Устанавливаем поверхность-приёмник AhiDrawSurfDstSet( dCtx, sDisp, 0 );
- Установить поверхность-источник
Обычно для этой роли используют либо пользовательскую поверхность с нужной к выводу картинкой, либо системную внеэкранную поверхность (см. Двойная буферизация).// Сохраним сюда системную внеэкранную поверхность AHISURFACE_T sDraw; // Получим системную внеэкранную поверхность sDraw = DAL_GetDrawingSurface( DISPLAY_MAIN ); // Устанавливаем поверхность-источник AhiDrawSurfSrcSet( dCtx, sDraw, 0 );
- Установить области вырезания для приёмника и источника
Пока что выключим их, и для этого передадим в функции AhiDrawClipDstSet и AhiDrawClipSrcSet - NULL:// Выключаем области вырезания для приёмника и источника AhiDrawClipDstSet( dCtx, NULL ); AhiDrawClipSrcSet( dCtx, NULL );
- Установить растровую операцию
Чтобы не углубляться в рамках этой статьи в растровые операции, ограничимся пока что простым правилом: Для вывода растровых изображений устанавливаем AHIROP_SRCCOPY, а для рисования цветом - AHIROP_PATTERN. Отсановимся на последнем, так как пригодится в последующем примере.// Устанавливаем растровую операцию на применение кисти AhiDrawRopSet( dCtx, AHIROP3(AHIROP_PATTERN) );
- Настроить кисть
Это делать не обязательно, если мы не собираемся рисовать графические примитивы. Но так как мы собираемся, то...// Установим кисть на самую обычную, сплошную (SOLID) AhiDrawBrushSet(devCx, NULL, NULL, 0x0, AHIFLAG_BRUSH_SOLID);
Конечно, некоторые из этих операций понадобится повторить перед вызовом определённых функций, с другими установками, но надеюсь это уже не составит для Вас проблем.
Проба пера
Наконец, всё готово для того, чтобы что-нибудь уже нарисовать. Не будем здесь заострять внимание на таких тривиальных вещах, как размещение последующих примеров в коде и инициализация приложения. Пускай, например, это будет вызов в таймере.
Для первого раза нарисуем цветной графический примитив.
// Вспомогательная переменная для указания области экрана AHIRECT_T rect; // Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы AhiDrawBrushFgColorSet(devCx, ATI_565RGB(0,0,255)); // Ярко-синий // Зададим прямоугольник на экране, который будет залит нашим цветом 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)