CreateCompatibleBitmap и CreateDIBSection (контроллеры памяти) - PullRequest
8 голосов
/ 21 сентября 2011

из того, что я прочитал здесь , похоже, что большинство функций Windows GDI ускорены. Так, например, вызов BitBlt или AlphaBlend использует аппаратное ускорение, если оно доступно. Также упоминается, что содержимое окна хранится только в видеопамяти. Теперь это все хорошо и верно для окна DC , но как я могу использовать память DC , которая находится в памяти видеокарты? И как только мы добьемся того, как получить прямой доступ к пикселям, я думаю, что это будет включать: 1. временное копирование данных в системную память 2. изменение данных пикселей 3. копирование обратно в видеопамять.

Я пробовал два подхода, оба выделяют системную память, как я вижу в диспетчере задач ...

  1. CreateCompatibleBitmap

    HDC hDC = GetDC(NULL);
    m_hDC = CreateCompatibleDC(hDC);
    m_hBmp = CreateCompatibleBitmap(hDC, cx, cy);
    ReleaseDC(NULL, hDC);
    
    m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);
    

    и затем вызовите, чтобы получить биты

    GetBitmapBits(...)
    

    Согласно различным комментариям это действительно должно создать совместимое растровое изображение в видеопамяти, но почему я все еще вижу увеличение системной памяти (даже когда я не вызываю GetBitmapBits)?

  2. CreateDIBSection

    HDC hDC = GetDC(NULL);
    m_hDC = CreateCompatibleDC(hDC);
    
    BITMAPINFO bmi;
    memset(&bmi, 0, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = cx;
    bmi.bmiHeader.biHeight = -cy; // top-down
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    m_hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&m_pBits, NULL, NULL);
    
    ReleaseDC(NULL, hDC);
    
    m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);
    

    в этом случае мы сразу получаем указатель на биты (m_pBits), поэтому очевидно, что они находятся в системной памяти ...

Или это копия, которая хранится в системной памяти для обоих методов? Но если я изменю биты в системной памяти, вызову BitBlt все равно придется снова проверять / копировать из системной памяти ... не очень оптимизированный ИМХО.

РЕДАКТИРОВАТЬ: Я также пытался создавать DC памяти с помощью BeginBufferedPaint и GetBufferedPaintBits. Он также распределяет системную память, поэтому в этом отношении я полагаю, что это просто оболочка для вышеуказанных методов, но кеширует DC, поэтому при следующем вызове не обязательно воссоздавать DC памяти. См. Статью Рэймонда Чена .

РЕДАКТИРОВАТЬ # 2: я предполагаю, что фактический вопрос: Правильно ли я делаю создание DC памяти в методе 1 или 2, чтобы получить аппаратно ускоренные операции GDI? Мне все кажется быстрым, и оба метода обеспечьте ту же скорость, так что на самом деле нет способа проверить это ...

1 Ответ

4 голосов
/ 22 сентября 2011

DC памяти не создаются на устройстве. Они предназначены для ввода вывода GDI в память.

С Контекст устройства памяти на MSDN:

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

Если вам нужна аппаратная ускоренная 2-мерная графика, вам следует рассмотреть возможность использования Direct2D .

...