Что-то не в порядке с Directdraw...

Тема в разделе "MS Visual C++", создана пользователем -, 10 окт 2010.

  1. Гость

    Читал на сайте cyberguru.ru "Получение прямого доступа к видеопамяти средствами DirectDraw", списал оттуда весь код, но он не работает (а именно, не хочет создавать поверхность). Вот код программы:
    Код (C++):
    #include "stdafx.h"
    #include <ddraw.h>
    #pragma comment (lib, "ddraw.lib")

    int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR    lpCmdLine,
    int   nCmdShow)
    {
    IDirectDraw *dd;
    HRESULT hdr = DirectDrawCreate (NULL, &dd, NULL);
    dd->SetCooperativeLevel (NULL, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
    dd->SetDisplayMode (800, 600, 8);
    DDSURFACEDESC desc;
    ZeroMemory (&desc, sizeof (DDSURFACEDESC));
    desc.dwSize = sizeof (DDSURFACEDESC);
    desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    desc.dwFlags = DDSD_CAPS;
    IDirectDrawSurface *sf;
    HRESULT hr = dd->CreateSurface (&desc, &sf, NULL);
    if (hr != DD_OK)
    MessageBox (0, "Error CreateSurface!", 0, 0);
    sf->Lock (NULL, &desc, DDLOCK_WAIT, NULL);
    sf->Unlock (desc.lpSurface);
    Sleep (1000);
    dd->Release ();
    return 0;
    }
    Программа выводит MessageBox и висит. Не знаю, что делать. Помогите, если кто-то знает!
     
  2. DarkKnight

    DarkKnight Well-Known Member
    C\C++ Team

    Регистрация:
    1 авг 2010
    Сообщения:
    653
    Симпатии:
    0
    Тут мое мнение проблема только в том, что ты не создаешь главное окно и не регистрируешь его класс....
    Но я могу правда и ошибаться, может при прямом доступе к видеопамяти (даже в Win) и не обязательно создавать окно, но я бы точно бы создал....
    WNDCLASSEX Okno; //и пошел
    ...
    ..
    .
    //Класс, регстрция класса, создания окна класса, обработчик событий... Ну и твой код... И бесконечный цикл обаботки MSG Win...
    Ну опять же говорю, что я могу и ошибаться, могу только тоно сказать, что DirectDraw - должен работать на сабзе Win-Application (из этого могу предположить, что должно быть хотя бы окно)
     
  3. mibin

    mibin Well-Known Member

    Регистрация:
    29 янв 2009
    Сообщения:
    48
    Симпатии:
    0
    А вообще где ты определяешь сам директ икс? Помоему если я все правильно помню..сначало нужно определить то что ты работаешь с директоиксом каким а дирет дро это часть него уже
     
  4. DarkKnight

    DarkKnight Well-Known Member
    C\C++ Team

    Регистрация:
    1 авг 2010
    Сообщения:
    653
    Симпатии:
    0
    Не, определено у него все правельно...
    Хедер указан, lib присоединен... Так что доступ к DirectDraw он точно получает...
     
  5. mibin

    mibin Well-Known Member

    Регистрация:
    29 янв 2009
    Сообщения:
    48
    Симпатии:
    0
    Попробуй создать с помощью DirectDrawCreateEx...
    и добавь обработчик события на создание и на установку уровня взаимодействия, может интерфейс проблема раньше возникла
     
  6. DarkKnight

    DarkKnight Well-Known Member
    C\C++ Team

    Регистрация:
    1 авг 2010
    Сообщения:
    653
    Симпатии:
    0
    Не, я проверял, этот участок кода у него точно работает, так как разрешение меняется и реально эксклюзив-доступ есть... А вот поверхность не хочет... Все равно думаю что оконное приложение должно быть... Лень проверить пока что...

     
  7. Гость

    Вы были, как всегда, правы. Только есть одно 'но':
    Можно и просто WNDCLASS. А вот функция GetForegroundWindow () подойдёт?
    На дату прошу не смотреть, так как я был занят совсем другим и мне было просто не до кодебая.
     
  8. Гость

    Что-то на мой вопрос долго не приходит ответ. У меня возник ещё один вопрос: если у меня 24-разрядный формат пикселя - как мне создать тип данных размером в 3 байта???
     
  9. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Попробуй лучше GetDesktopWindow()

    Код (C++):
    typedef struct {
    unsigned char  r, g, b;
    } color;
     
  10. Гость

    :facepalm: Что-то я не знал про эту функцию...
    А не структуру вряд ли получится.
    P. S. А зачем вообще писать typedef struct { ... } color; если можно struct color { ... };???
     
  11. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Получится.

    Для того, чтобы определить color как тип а не как переменную. Тебе же именно тип нужен был.
     
  12. Гость

    Интересно, как?
    Но я же сказал - struct color { ... }; Это же тоже создаёт тип.
     
  13. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Сформулируй вопрос понятным образом, а то я могу не совсем точно понять о чем ты спрашиваешь.
    С ходу я понял что структура, как ты думаешь, не подойдет для этого случая. Правильно я понял?

    Это по-сути одно и то же. Просто я привык к такому синтаксису.
     
  14. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Партизан
    Кстати, если использовать 4-х байтовый тип данных, то скорость записи в память возрастет; А если же ты будешь писать в 8-битном режиме то я могу тебе описать самый быстрый (какой только возможен на С) вариант.
     
  15. Гость

    Это не так важно, просто мне интересно. Я говорю про что-то вроде этого:
    Код (C++):
    typedef XXX color; // Размер XXX - 3 байта. Это не класс и не структура.
    И что это за вариант? Опишите, пожалуйста.
     
  16. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Этот случай актуален только при записи в 8-битном режиме, т.е. если тебя интересует 8-битный режим.

    Суть в том, чтобы писать не байтами, а двойными словами (т.е. четырехбайтными порциями), при чем выровненными по границе, кратной 4-ке. Этот способ дает очень хороший результат при правильном применении. Его так же можно использовать при заполнении памяти определенным значением (как memset() в Си), и работать это будет очень быстро.

    Вот пример из заполнения строки при рисовании треугольника (взято из старых примеров Watcom C++):

    Код (C++):
    void fill( BYTE *p, int x0, int x1, DWORD c )
    {
    int dx, z;
    dx = x1 - x0 + 1;
    p += x0;
    if ( dx > 4 ) {
    if ( z = (DWORD)p & 3 ) {
    while ( z++ < 4 ) {
    *p++ = (BYTE)c;
    dx--;
    }
    }
    while ( dx >= 4 ) {
    *((DWORD *)p) = c;
    p += 4;
    dx -= 4;
    }
    }
    while ( dx-- > 0 ) *p++ = (BYTE)c;
    }
     
  17. Гость

    Не совсем понятно, как он работает. Что значат аргументы x0 и x1? Что значат локальные переменные dx и z? Без комментариев и понятных названий, как видите, разобрать ничего невозможно и даже одна функция превращается в кучу непонятного кода.
     
  18. lazybiz

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    Вот тебе наглядный пример работы. Если тебе и тут не совсем понятно, то уж извини.
    Код (C++):
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <mem.h>

    //
    // sizeof( u8 ) == 1
    // sizeof( u32 ) == 4
    //
    typedef unsigned char       u8;
    typedef unsigned long       u32;

    #define TEST_SIZE           (1024 * 1024 * 8)
    #define TEST_VALUE          123
    #define TEST_ITERATIONS     500

    void fill_asm( u8 *, u8, u32 );
    #pragma aux fill_asm =                      \
    "       mov     ah, al                  "   \
    "       shl     eax, 8                  "   \
    "       mov     al, ah                  "   \
    "       shl     eax, 8                  "   \
    "       mov     al, ah                  "   \
    "       lea     ecx, [edi + edi * 2]    "   \
    "       and     ecx, 3                  "   \
    "       sub     esi, ecx                "   \
    "       jle     short leb               "   \
    "       rep     stosb                   "   \
    "       mov     ecx, esi                "   \
    "       and     esi, 3                  "   \
    "       shr     ecx, 2                  "   \
    "       rep     stosd                   "   \
    "leb:   add     ecx, esi                "   \
    "       rep     stosb                   "   \
    parm    [edi] [al] [esi]            \
    modify exact [eax ecx esi edi];


    void fill_c( u8 *p, u8 v, u32 n )
    {
    u32 z, c;
    c = v;
    c |= c << 8;
    c |= c << 16;
    if ( n > 4 ) {
    if ( z = (u32)p & 3 ) {
    while ( z++ < 4 ) {
    *p++ = (u8)c;
    n--;
    }
    }
    while ( n >= 4 ) {
    *((u32 *)p) = c;
    p += 4;
    n -= 4;
    }
    }
    while ( n-- > 0 ) *p++ = (u8)c;
    }

    void main()
    {
    int     i, j, k;
    DWORD   time;
    u8 *    p;

    p = (u8 *)malloc( TEST_SIZE );
    if ( !p ) {
    printf( "malloc( %d ) failed.\n", TEST_SIZE );
    return;
    }

    printf( "wait 3 seconds...\n" );
    Sleep( 3000 );


    memset( p, TEST_VALUE, TEST_SIZE );
    fill_c( p, TEST_VALUE, TEST_SIZE );
    fill_asm( p, TEST_VALUE, TEST_SIZE );

    for ( k = 0; k < 8; k++ ) {
    printf( "\nbuffer size: %d, iterations: %d\n", TEST_SIZE >> k, TEST_ITERATIONS );


    printf( "memset(): " );
    time = timeGetTime();
    for ( j = 0; j < 10; j++ ) {
    for ( i = 0; i < TEST_ITERATIONS; i++ ) {
    memset( p + j, TEST_VALUE, (TEST_SIZE >> k) - j );
    }
    }
    time = timeGetTime() - time;
    printf( "%5.2f seconds\n", (double)time / 1000.0 );


    printf( "fill_c(): " );
    time = timeGetTime();
    for ( j = 0; j < 10; j++ ) {
    for ( i = 0; i < TEST_ITERATIONS; i++ ) {
    fill_c( p + j, TEST_VALUE, (TEST_SIZE >> k) - j );
    }
    }
    time = timeGetTime() - time;
    printf( "%5.2f seconds\n", (double)time / 1000.0 );


    printf( "fill_asm(): " );
    time = timeGetTime();
    for ( j = 0; j < 10; j++ ) {
    for ( i = 0; i < TEST_ITERATIONS; i++ ) {
    fill_asm( p + j, TEST_VALUE, (TEST_SIZE >> k) - j );
    }
    }
    time = timeGetTime() - time;
    printf( "%5.2f seconds\n", (double)time / 1000.0 );
    }

    free( p );
    }
    Результат у меня выдал такой:
     

    Вложения:

    • fill_test.png
      fill_test.png
      Размер файла:
      97,6 КБ
      Просмотров:
      20
Загрузка...

Поделиться этой страницей