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

Двойная буферизация: различия между версиями

(Ссылка вику и подкорректировал определение)
 
(не показаны 3 промежуточные версии 1 участника)
Строка 1:Строка 1:
Двойная буферизация ({{lang-en|Double Buffering}}) — метод вывода графики на экран через драйвер, который применяется для предотвращения эффекта "мерцания".
+
Двойная буферизация ({{lang-en|Double Buffering}}) — метод вывода графики на экран через драйвер, который применяется в приложениях, активно использующих вывод графики через [[AHI|драйвер дисплея]] в полноэкранном режиме. Используется как метод повышения производительности за счет избыточного использования [[видеопамяти]].
  
 
== Описание ==
 
== Описание ==
Строка 5:Строка 5:
 
При использовании метода "двойной буферизации", графика сначала выводится во вторичный буфер (в данном случае на [[AHI#Поверхности|поверхность]]), а затем первичный буфер подменяется на вторичный.
 
При использовании метода "двойной буферизации", графика сначала выводится во вторичный буфер (в данном случае на [[AHI#Поверхности|поверхность]]), а затем первичный буфер подменяется на вторичный.
  
 +
== Применение ==
  
 +
Перед началом вывода графики необходимо чтобы у нас был [[AHI#Контекст устройства|контекст устройства]] ('''dCtx'''), на которое будем выводить графику и две [[AHI#Поверхности|поверхности]] - экранная поверхность ('''sDisp''') и внеэкранная поверхность ('''sDraw'''). Если у нас их нет - смотрим [[AHI#Инициализация|здесь]] как их получить. Как только получены поверхности, мы сохраняем их в дополнительные переменные '''sRealDisp''' и '''sRealDraw''', т.к. они нам ещё понадобятся.
  
На данный момент статья ещё не написана до конца. Если вам необходим пример предотвращения мерцания при выводе графики на дисплей, вы можете перейти по этой ссылке: [[Предотвращение мерцания]]
+
Итак, графика инициализирована. Можем приступать к работе.
 +
 
 +
<ol>
 +
<li>'''Перед выводом графики мы меняем поверхность, на которой будем рисовать'''<br>
 +
По-умолчанию этой поверхностью является экранная поверхность. Но для наших целей она не подходит. Переключаем поверхность с помощью функции [[AhiDrawSurfDstSet]]:
 +
<pre>
 +
AhiDrawSurfDstSet(dCtx, sDraw, 0);
 +
</pre>
 +
</li>
 +
 
 +
<li>'''Собственно, выводим графику'''<br>
 +
Выводим графику. Не забываем устанавливать [[Raster Operations|растровую операцию]] и цвет кисти:
 +
<pre>
 +
// Вспомогательная переменная для указания области экрана
 +
AHIRECT_T rect;
 +
 
 +
// Устанавливаем растровую операцию на применение кисти
 +
AhiDrawRopSet(dCtx, AHIROP3(AHIROP_PATCOPY));
 +
 
 +
// Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы
 +
AhiDrawBrushFgColorSet(dCtx, ATI_565RGB(0,0,255)); // Ярко-синий
 +
 
 +
// Зададим прямоугольник на экране, который будет залит нашим цветом
 +
rect.x1 = 0;
 +
rect.y1 = 0;
 +
rect.x2 = 64;
 +
rect.y2 = 64;
 +
 
 +
// Нарисуем прямоугольник rect
 +
AhiDrawSpans(dCtx, &rect, 1, 0);
 +
</pre>
 +
</li>
 +
 
 +
<li>'''Заменяем экранную поверхность'''<br>
 +
Графика выведена во внеэкранную поверхность, но теперь её нужно вывести на экран. Для этого мы устанавливаем '''sDraw''' экранной поверхностью, а '''sDisp''' - поверхностью для рисования и меняем местами значения переменных '''sDisp''' и '''sDraw''':
 +
<pre>
 +
AHISURFACE_T tSurface;
 +
 
 +
// Установка экранной поверхности
 +
AhiDispSurfSet(dCtx, sDraw, 0);
 +
// Установка поверхности для рисования
 +
AhiDrawSurfDstSet(dCtx, sDisp, 0);
 +
 
 +
// Изображение получено на экране
 +
 
 +
// Меняем поверхности местами
 +
tSurface = sDisp;
 +
sDisp = sDraw;
 +
sDraw = tSurface;
 +
</pre>
 +
 
 +
Далее повторяем все действия с первого пункта, пока необходимо выводить графику
 +
</li>
 +
 
 +
<li>'''Возвращаем значения sDisp и sDraw'''<br>
 +
Перед выходом из эльфа '''ОБЯЗАТЕЛЬНО''' необходимо вернуть их значения, которые были выданы телефоном. Т.к. не известно, в какой из двух переменных ('''sDisp''' или '''sDraw''') находится реальная экранная поверхность, мы воспользуемся переменными '''sRealDisp''' и '''sRealDraw''', о которых говорилось в самом начале.
 +
<pre>
 +
// Установка экранной поверхности
 +
AhiDispSurfSet(dCtx, sRealDisp, 0);
 +
// Установка поверхности для рисования
 +
AhiDrawSurfDstSet(dCtx, sRealDraw, 0);
 +
</pre>
 +
 
 +
И только тогда выходим из эльфа.
 +
</li>
 +
 
 +
</ol>
 +
 
 +
== См. также ==
 +
 
 +
* [[AHI]] - драйвер для чипов ATI
 +
* [[LdrDisplayCbkReg]] - функция для создания callback'ов для рисования поверх [[UIS]]
 +
* [[LdrDisplayCbkUnReg]] - функция для удаления callback'ов, созданных с помощью [[LdrDisplayCbkReg]]
 +
* [[Предотвращение мерцания]] - Классический метод предотвращения мерцания при выводе графики
 +
 
 +
== Ссылки ==
 +
[http://ru.wikipedia.org/wiki/Двойная_буферизация Wikipedia(RU): Двойная буферизация]
 +
 
 +
 
 +
[[Категория:Эльфостроение]]

Текущая версия на 16:52, 12 июня 2010

Двойная буферизация (англ. Double Buffering) — метод вывода графики на экран через драйвер, который применяется в приложениях, активно использующих вывод графики через драйвер дисплея в полноэкранном режиме. Используется как метод повышения производительности за счет избыточного использования видеопамяти.

Описание

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

Применение

Перед началом вывода графики необходимо чтобы у нас был контекст устройства (dCtx), на которое будем выводить графику и две поверхности - экранная поверхность (sDisp) и внеэкранная поверхность (sDraw). Если у нас их нет - смотрим здесь как их получить. Как только получены поверхности, мы сохраняем их в дополнительные переменные sRealDisp и sRealDraw, т.к. они нам ещё понадобятся.

Итак, графика инициализирована. Можем приступать к работе.

  1. Перед выводом графики мы меняем поверхность, на которой будем рисовать
    По-умолчанию этой поверхностью является экранная поверхность. Но для наших целей она не подходит. Переключаем поверхность с помощью функции AhiDrawSurfDstSet:
    AhiDrawSurfDstSet(dCtx, sDraw, 0);
  2. Собственно, выводим графику
    Выводим графику. Не забываем устанавливать растровую операцию и цвет кисти:
    // Вспомогательная переменная для указания области экрана
    AHIRECT_T	rect;
    // Устанавливаем растровую операцию на применение кисти
    AhiDrawRopSet(dCtx, AHIROP3(AHIROP_PATCOPY));
    // Установим цвет кисти. Этим цветом будут выводиться наши графические примитивы
    AhiDrawBrushFgColorSet(dCtx, ATI_565RGB(0,0,255)); // Ярко-синий
    // Зададим прямоугольник на экране, который будет залит нашим цветом
    rect.x1 = 0;
    rect.y1 = 0;
    rect.x2 = 64;
    rect.y2 = 64;
    // Нарисуем прямоугольник rect
    AhiDrawSpans(dCtx, &rect, 1, 0);
  3. Заменяем экранную поверхность
    Графика выведена во внеэкранную поверхность, но теперь её нужно вывести на экран. Для этого мы устанавливаем sDraw экранной поверхностью, а sDisp - поверхностью для рисования и меняем местами значения переменных sDisp и sDraw:
    AHISURFACE_T	tSurface;
    // Установка экранной поверхности
    AhiDispSurfSet(dCtx, sDraw, 0);
    // Установка поверхности для рисования
    AhiDrawSurfDstSet(dCtx, sDisp, 0);
    // Изображение получено на экране
    // Меняем поверхности местами
    tSurface = sDisp;
    sDisp = sDraw;
    sDraw = tSurface;

    Далее повторяем все действия с первого пункта, пока необходимо выводить графику

  4. Возвращаем значения sDisp и sDraw
    Перед выходом из эльфа ОБЯЗАТЕЛЬНО необходимо вернуть их значения, которые были выданы телефоном. Т.к. не известно, в какой из двух переменных (sDisp или sDraw) находится реальная экранная поверхность, мы воспользуемся переменными sRealDisp и sRealDraw, о которых говорилось в самом начале.
    // Установка экранной поверхности
    AhiDispSurfSet(dCtx, sRealDisp, 0);
    // Установка поверхности для рисования
    AhiDrawSurfDstSet(dCtx, sRealDraw, 0);

    И только тогда выходим из эльфа.

См. также

Ссылки

Wikipedia(RU): Двойная буферизация