Re[19]: а если память уже выделена?
От: swamp Россия  
Дата: 09.07.03 14:49
Оценка:
Здравствуйте, PavZ, Вы писали:

S>> А как сделать MySurface из сырого битмапа (т.е. указателя на данные, ширины/высоты, глубины цвета и т.п.)?


PZ>В SDK есть модуль ddutil.h ( соотв. ddutil.pas ) в нем есть функция DDLoadBitmap(LPSTR *Filename, ...);


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

PZ>битности и пр.

Вообще-то мой битмап уже в памяти, так что конкретно такая функция не катит Но тем не менее за наводку спасибо, завтра поставлю DirectX SDK (я так понимаю ты имеешь ввиду именно его?) и буду смотреть...
Sincerely yours,
Andrew Simontsev.
Re[20]: а если память уже выделена?
От: PavZ  
Дата: 09.07.03 14:56
Оценка:
Здравствуйте, swamp, Вы писали:

S>Здравствуйте, PavZ, Вы писали:


S>>> А как сделать MySurface из сырого битмапа (т.е. указателя на данные, ширины/высоты, глубины цвета и т.п.)?


PZ>>В SDK есть модуль ddutil.h ( соотв. ddutil.pas ) в нем есть функция DDLoadBitmap(LPSTR *Filename, ...);


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

PZ>>битности и пр.

S> Вообще-то мой битмап уже в памяти, так что конкретно такая функция не катит Но тем не менее за наводку спасибо, завтра поставлю DirectX SDK (я так понимаю ты имеешь ввиду именно его?) и буду смотреть...


Там , если посмотреть реализацию то легко и из памяти загрузить.
Помоему даже при помощи доп. флажков решается.
Re[15]: а если память уже выделена?
От: Hacker_Delphi Россия  
Дата: 09.07.03 16:25
Оценка:
Здравствуйте, PavZ, Вы писали:

PZ>Из возможностей DirectDraw помоему лучше использовать только


PZ>FDDSPrimary.Lock.

PZ> Скопировать необх. данные ...
PZ>FDDSPrimary.Unlock.

PZ>или


PZ>FDDSBack.Lock.

PZ> Скопировать необх. данные ...
PZ>FDDSBack.Unlock.
PZ>Flip;

PZ>ну и установку видеорежима.


PZ>создавать доп. поверхности = доп. гемор...

PZ>лучшая поверхность — выделить просто кусок оперативки...
Интереса для попробуй свой подход сравнить с подходом OFFSCREEN_SURFACE + BltFaast на видеокарточке типа GeForce...
если пробовать писать руками в видеопамять на GeForce — гарантированы тормоза... а если создать OFFSCREEN_SURFACE + SYSTEM_MEMORY... то тормоза пропадают...
так что твой солюшн — не лучший...
да и при подходе, который привожу я (про работу с поверхностями в системной памяти) тоже тормоза есть... я такой подход только при реализации Alpha Blend'а пользовал...
... << RSDN@Home 1.1 alpha 1 >>
Если при компиляции и исполнении вашей программы не происходит ни одной ошибки — это ошибка компилятора :)))
Re[16]: а если память уже выделена?
От: Аноним  
Дата: 09.07.03 20:21
Оценка:
H_D>Интереса для попробуй свой подход сравнить с подходом OFFSCREEN_SURFACE + BltFaast на видеокарточке типа GeForce...
H_D>если пробовать писать руками в видеопамять на GeForce — гарантированы тормоза... а если создать OFFSCREEN_SURFACE + SYSTEM_MEMORY... то тормоза пропадают...

Cорри, на GeForce завтра попробую у товарища. Сейчас потестил на своей карте TNT2.
======================================================
1000 Копирований на Primary Surface (640х480 16 bit)
======================================================
ВLTFAST — 30 сек.

Копирование руками (ASM) — 5 сек.
-----------------------------------------------------
Впринципе я где-то полгода назад проводил тест, написал тестовую программу по копированию
из разных типов памяти (SYS->VID) (VID->VID) (VID->SYS) (SYS->SYS) разными способами,
несколько алгоритмов на ASM а также при помощи функций BltFast.
тест прошел примерно на 20 компах (там 2 из них были с Geforce). Вывод получился один.->
-----------------------
Обновление экрана
-----------------------
Primary.Lock
Копируем нужные участки (ASM)
Primary Unlock
-----------------------


-----------------------
Игровой Цикл
-----------------------
копирование только SYS->SYS на ASM.
-----------------------
Re[16]: а если память уже выделена?
От: PavZ  
Дата: 09.07.03 20:21
Оценка:
H_D>Интереса для попробуй свой подход сравнить с подходом OFFSCREEN_SURFACE + BltFaast на видеокарточке типа GeForce...
H_D>если пробовать писать руками в видеопамять на GeForce — гарантированы тормоза... а если создать OFFSCREEN_SURFACE + SYSTEM_MEMORY... то тормоза пропадают...

Cорри, на GeForce завтра попробую у товарища. Сейчас потестил на своей карте TNT2.
======================================================
1000 Копирований на Primary Surface (640х480 16 bit)
======================================================
ВLTFAST — 30 сек.

Копирование руками (ASM) — 5 сек.
-----------------------------------------------------
Впринципе я где-то полгода назад проводил тест, написал тестовую программу по копированию
из разных типов памяти (SYS->VID) (VID->VID) (VID->SYS) (SYS->SYS) разными способами,
несколько алгоритмов на ASM а также при помощи функций BltFast.
тест прошел примерно на 20 компах (там 2 из них были с Geforce). Вывод получился один.->
-----------------------
Обновление экрана
-----------------------
Primary.Lock
Копируем нужные участки (ASM)
Primary Unlock
-----------------------


-----------------------
Игровой Цикл
-----------------------
копирование только SYS->SYS на ASM.
-----------------------
Re[18]: а если память уже выделена?
От: Блудов Павел Россия  
Дата: 10.07.03 03:23
Оценка: 3 (1)
Здравствуйте, swamp, Вы писали:

S> А как сделать MySurface из сырого битмапа (т.е. указателя на данные, ширины/высоты, глубины цвета и т.п.)?


DDSURFACEDESC2 dd = {0};

dd.dwSize = sizeof(DDSURFACEDESC2);
dd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
dd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
dd.dwHeight = nHeight;
dd.dwWidth = nWidth;
dd.lPitch = nPitch;
dd.lpSurface = pBits;
dd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
dd.ddpfPixelFormat.dwFlags= DDPF_RGB;

// X8R8G8B8 firmat
dd.ddpfPixelFormat.dwRGBBitCount = 32;
dd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
dd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
dd.ddpfPixelFormat.dwBBitMask = 0x000000FF;

hr = m_pDirectDraw7->CreateSurface(&dd, &m_pSurface7, NULL);


Этот пример создает 32-x битный IDirectDrawSurface с указанными
nHeight, nWidth, nPitch и pBits;

Павел.
Re[19]: а если память уже выделена?
От: swamp Россия  
Дата: 10.07.03 07:49
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>Здравствуйте, swamp, Вы писали:


S>> А как сделать MySurface из сырого битмапа (т.е. указателя на данные, ширины/высоты, глубины цвета и т.п.)?


БП>
БП>DDSURFACEDESC2 dd = {0};

...

БП>hr = m_pDirectDraw7->CreateSurface(&dd, &m_pSurface7, NULL);
БП>


БП>Этот пример создает 32-x битный IDirectDrawSurface с указанными

БП>nHeight, nWidth, nPitch и pBits;

Спасибо, Павел, это то что нужно. Однако попытавшись сделать аналогичное, столкнулся с проблемой:


        DDSURFACEDESC dd={0};
        dd.dwSize = sizeof(DDSURFACEDESC2);
        dd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS | DDSD_LPSURFACE | DDSD_PITCH | DDSD_PIXELFORMAT;
        dd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
        dd.dwHeight = m_curData->height; // m_curData - это структура, где все хранится...
        dd.dwWidth = m_curData->width;
        dd.lPitch = m_curData->stride;  // если я правильно понял - pitch = stride?
        dd.lpSurface = m_curData->data;
        dd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
        dd.ddpfPixelFormat.dwFlags= DDPF_RGB;

        // X8R8G8B8 firmat
        dd.ddpfPixelFormat.dwRGBBitCount = 32;
        dd.ddpfPixelFormat.dwRBitMask = 0x00FF0000;
        dd.ddpfPixelFormat.dwGBitMask = 0x0000FF00;
        dd.ddpfPixelFormat.dwBBitMask = 0x000000FF;

        //CAggDirectDraw dirdraw(_T("test"),NULL);
        CComPtr<IDirectDraw> piDraw;
        CComPtr<IDirectDrawSurface> piSurf;
        HRESULT hr = DirectDrawCreate(NULL, &piDraw,NULL);
        if (FAILED(hr))
            return hr;
        hr = piDraw->SetCooperativeLevel(NULL, DDSCL_NORMAL);
        if (FAILED(hr))
            return hr;
        hr = piDraw->CreateSurface(&dd, &piSurf, NULL);
        if (FAILED(hr))
            return hr; // возвращает E_INVALIDARG... :(
        HDC tempDC=NULL;
        hr = piSurf->GetDC(&tempDC);
        if (FAILED(hr))
            return hr;
        item->DrawOnHdc(tempDC); // тут происходит рисование, впрочем это не важно...
        hr = piSurf->ReleaseDC(tempDC);
        if (FAILED(hr))
            return hr;


Проблема в том, что CreateSurface возвращает E_INVALIDARG. Может структуру DDSURFACEDESC надо заполнять иначе чем DDSURFACEDESC2? Вроде мемберы все одни и те же...
Sincerely yours,
Andrew Simontsev.
Re[20]: а если память уже выделена?
От: PavZ  
Дата: 10.07.03 08:22
Оценка:
S>[ccode]
S> DDSURFACEDESC dd={0};
S> dd.dwSize = sizeof(DDSURFACEDESC2);

Структура имеет тип DDSURFACEDESC а передаешь размер от второй версии структуры.
Либо
dd.dwSize = sizeof(DDSURFACEDESC);
Либо
DDSURFACEDESC2 dd={0};


Раз юзаешь DirectDrawSurface то нужно первый вариант писать. dd.dwSize = sizeof(DDSURFACEDESC);
Re[21]: а если память уже выделена?
От: swamp Россия  
Дата: 10.07.03 10:02
Оценка:
Здравствуйте, PavZ, Вы писали:


S>>[ccode]

S>> DDSURFACEDESC dd={0};
S>> dd.dwSize = sizeof(DDSURFACEDESC2);

PZ>Структура имеет тип DDSURFACEDESC а передаешь размер от второй версии структуры.

PZ>Либо
PZ> dd.dwSize = sizeof(DDSURFACEDESC);
PZ>Либо
PZ> DDSURFACEDESC2 dd={0};


PZ>Раз юзаешь DirectDrawSurface то нужно первый вариант писать. dd.dwSize = sizeof(DDSURFACEDESC);



И в самом деле Хотя после исправления, проблема осталась. Читал доку, нашел вот что про структуру DDSCAPS (точнее про флаг DDSCAPS_SYSTEMMEMORY который я юзаю):

DDSCAPS_SYSTEMMEMORY — This surface memory was allocated from system memory. If this capability bit is set by the Windows 2000 or later driver, DirectDraw is disabled.

Не означает ли это, что на 2000 и выше это дело работать и не должно? Или что значит "DirectDraw is disabled"?
Sincerely yours,
Andrew Simontsev.
Re[22]: а если память уже выделена?
От: PavZ  
Дата: 10.07.03 10:25
Оценка:
S> И в самом деле Хотя после исправления, проблема осталась. Читал доку, нашел вот что про структуру DDSCAPS (точнее про флаг DDSCAPS_SYSTEMMEMORY который я юзаю):

Попробуй отказаться от lpSurface и lPitch ( отключи флажки )...если не поможет, то и pixelformat
прибей. Мне кажеться ему не нравяться твои собственные lpSurface и lPitch, он сам любит распоряжаться что и куда засовывать.
Особено учитывая что это интерфейс первой версии. Попробуй для DirectDrawSurface7 сделать,
может там прокатит.


S> DDSCAPS_SYSTEMMEMORY — This surface memory was allocated from system memory. If this capability bit is set by the Windows 2000 or later driver, DirectDraw is disabled.

S> Не означает ли это, что на 2000 и выше это дело работать и не должно? Или что значит "DirectDraw is disabled"?

Возможно это означает что аппаратные возможности использоваться не будут. Хотя это только мой вариант перевода.
Re[23]: а если память уже выделена?
От: PavZ  
Дата: 10.07.03 10:31
Оценка:
Здравствуйте, PavZ, Вы писали:



S>> И в самом деле Хотя после исправления, проблема осталась. Читал доку, нашел вот что про структуру DDSCAPS (точнее про флаг DDSCAPS_SYSTEMMEMORY который я юзаю):


Еще вопрос на засыпку — чему равно stride ... по идее должно быть width*4
Re[24]: а если память уже выделена?
От: swamp Россия  
Дата: 10.07.03 11:08
Оценка:
Здравствуйте, PavZ, Вы писали:

PZ>Здравствуйте, PavZ, Вы писали:


S>>> И в самом деле Хотя после исправления, проблема осталась. Читал доку, нашел вот что про структуру DDSCAPS (точнее про флаг DDSCAPS_SYSTEMMEMORY который я юзаю):


PZ>Еще вопрос на засыпку — чему равно stride ... по идее должно быть width*4


В случае 32 бит на пиксель — да, а так там все сложнее...
Sincerely yours,
Andrew Simontsev.
Re[8]: а если память уже выделена?
От: B_A_D Израиль  
Дата: 10.07.03 11:08
Оценка:
Здравствуйте, swamp, Вы писали:

S> А можно что-нибудь сделать, если указатель на изображение уже имеется (имеется другая структура, преставляющая битмап)? Как получить HBITMAP так, чтобы он сам память не выделял (ну и соответсвенно не прибивал )?


---------------------------------------------------------------------------------------------

Вообще-то, если почитать MSDN, обнаруживаются интересные вещи:

CreateBitmap
The CreateBitmap function creates a bitmap with the specified width, height, and color format (color planes and bits per pixel).

HBITMAP CreateBitmap(
int nWidth, // bitmap width, in pixels
int nHeight, // bitmap height, in pixels
UINT cPlanes, // number of color planes used by device
UINT cBitsPerPel, // number of bits required to identify a color
CONST VOID *lpvBits // pointer to array containing color data
);


lpvBits — Pointer to an array of color data used to set the colors in a rectangle of pixels. Each scan line in the rectangle must be word aligned (scan lines that are not word aligned must be padded with zeros). If this parameter is NULL, the new bitmap is undefined.

то есть если при создании битмапины ты подсунешь ей указатель на твое изображение,
то после создания она будет содержать нужную тебе картинку. И никакого гесороя с
DirecxX.
Re[23]: а если память уже выделена?
От: swamp Россия  
Дата: 10.07.03 11:10
Оценка:
Здравствуйте, PavZ, Вы писали:



S>> И в самом деле Хотя после исправления, проблема осталась. Читал доку, нашел вот что про структуру DDSCAPS (точнее про флаг DDSCAPS_SYSTEMMEMORY который я юзаю):


PZ>Попробуй отказаться от lpSurface и lPitch ( отключи флажки )...если не поможет, то и pixelformat

PZ>прибей. Мне кажеться ему не нравяться твои собственные lpSurface и lPitch, он сам любит распоряжаться что и куда засовывать.
PZ>Особено учитывая что это интерфейс первой версии. Попробуй для DirectDrawSurface7 сделать,
PZ>может там прокатит.

Ок, надо попробовать, хотя в таком случае пропадет вся прелесть — совместимость со старыми версиями виндов...

S>> DDSCAPS_SYSTEMMEMORY — This surface memory was allocated from system memory. If this capability bit is set by the Windows 2000 or later driver, DirectDraw is disabled.

S>> Не означает ли это, что на 2000 и выше это дело работать и не должно? Или что значит "DirectDraw is disabled"?
PZ>Возможно это означает что аппаратные возможности использоваться не будут. Хотя это только мой вариант перевода.

А за что такая дискриминация?
Sincerely yours,
Andrew Simontsev.
Re[9]: а если память уже выделена?
От: Блудов Павел Россия  
Дата: 10.07.03 11:18
Оценка:
Здравствуйте, B_A_D, Вы писали:


B_A>Вообще-то, если почитать MSDN, обнаруживаются интересные вещи:

B_A>CreateBitmap
B_A>то есть если при создании битмапины ты подсунешь ей указатель на твое изображение,

Вы упустили один очень важный момент: нужно избежать копирования, А CreateBitmap
именно копирует их. Картинка 1600x1200x32 бита копиреутся очень долго.

Павел.
Re[10]: а если память уже выделена?
От: B_A_D Израиль  
Дата: 10.07.03 11:43
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

БП>Здравствуйте, B_A_D, Вы писали:



B_A>>Вообще-то, если почитать MSDN, обнаруживаются интересные вещи:

B_A>>CreateBitmap
B_A>>то есть если при создании битмапины ты подсунешь ей указатель на твое изображение,

БП>Вы упустили один очень важный момент: нужно избежать копирования, А CreateBitmap

БП>именно копирует их. Картинка 1600x1200x32 бита копиреутся очень долго.

БП>Павел.



Да, согласен. Ну если человек не хочет заморачиваться с DirectX,
почему бу ему действительно вместо выделения памяти так, как он делает
сейчас:

  MySurface = allocmem(SurfaceWidth*SurfaceHeight*(BPP/8));


не выделить память вот так:

 BITMAPINFO bi;
 bi.bmiHeader.biWidth  =  SurfaceWidth;
 bi.bmiHeader.biHeight =  SurfaceHeight;
 bi.bmiHeader.biBitCount = BPP;
 bi.bmiHeader.biSizeImage = SurfaceWidth*SurfaceHeight*(BPP/8); //с учетом выравнивания
 HBITMAP hMyBitmap = CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,MySurface);



и работай на здоровье по-всякому. Есть указатель, который выделяется только 1 раз
и есть HBITMAP, с которым можно работать функциями GDI.
Все проще, чем с DirectX.
Re[11]: а если память уже выделена?
От: swamp Россия  
Дата: 10.07.03 12:17
Оценка:
Здравствуйте, B_A_D, Вы писали:

B_A>Да, согласен. Ну если человек не хочет заморачиваться с DirectX,


Если речь идет обо мне, то я не против заморочиться с директом, если это решение будет совместимо со старыми версиями виндов и не выставлять требования к инсталляции дополнительных софтин (например, как я понимаю, если завязаться на DirectX7, то на 98й винде по умолчанию работать не будет)...

B_A>почему бу ему действительно вместо выделения памяти так, как он делает

B_A>сейчас:

B_A>
B_A>  MySurface = allocmem(SurfaceWidth*SurfaceHeight*(BPP/8));
B_A>


B_A>не выделить память вот так:


B_A>
B_A> BITMAPINFO bi;
B_A> bi.bmiHeader.biWidth  =  SurfaceWidth;
B_A> bi.bmiHeader.biHeight =  SurfaceHeight;
B_A> bi.bmiHeader.biBitCount = BPP;
B_A> bi.bmiHeader.biSizeImage = SurfaceWidth*SurfaceHeight*(BPP/8); //с учетом выравнивания
B_A> HBITMAP hMyBitmap = CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,MySurface);
B_A>


B_A>и работай на здоровье по-всякому. Есть указатель, который выделяется только 1 раз

B_A>и есть HBITMAP, с которым можно работать функциями GDI.
B_A>Все проще, чем с DirectX.

Я бы и рад, но проблема в том, что для хранения растра используется структура, альтернативная DIB. Поэтому так не покатит... Все-таки не понятно, почему не сделали возможность создания HBITMAP на основе всего готового без копирований...
Sincerely yours,
Andrew Simontsev.
Re[12]: а если память уже выделена?
От: PavZ  
Дата: 10.07.03 12:50
Оценка:
B_A>>почему бу ему действительно вместо выделения памяти так, как он делает
B_A>>сейчас:

B_A>>
B_A>>  MySurface = allocmem(SurfaceWidth*SurfaceHeight*(BPP/8));
B_A>>


B_A>>не выделить память вот так:


B_A>>
B_A>> BITMAPINFO bi;
B_A>> bi.bmiHeader.biWidth  =  SurfaceWidth;
B_A>> bi.bmiHeader.biHeight =  SurfaceHeight;
B_A>> bi.bmiHeader.biBitCount = BPP;
B_A>> bi.bmiHeader.biSizeImage = SurfaceWidth*SurfaceHeight*(BPP/8); //с учетом выравнивания
B_A>> HBITMAP hMyBitmap = CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,MySurface);
B_A>>


B_A>>и работай на здоровье по-всякому. Есть указатель, который выделяется только 1 раз

B_A>>и есть HBITMAP, с которым можно работать функциями GDI.
B_A>>Все проще, чем с DirectX.

S> Я бы и рад, но проблема в том, что для хранения растра используется структура, альтернативная DIB. Поэтому так не покатит... Все-таки не понятно, почему не сделали возможность создания HBITMAP на основе всего готового без копирований...


Мне кажется B_A_D предложил хороший метод. А как ты память выделяешь, m_curData->data;
этот указатель как получается ?
Если это GetMem,allocmem и прочее то почему бы не выделить при помощи CreateDIBSection ...получится тот же указатель + HDC.По крайней мере я так понял, пока не юзал.
Re[16]: а если память уже выделена?
От: PavZ  
Дата: 11.07.03 06:26
Оценка:
H_D>Интереса для попробуй свой подход сравнить с подходом OFFSCREEN_SURFACE + BltFaast на видеокарточке типа GeForce...
H_D>если пробовать писать руками в видеопамять на GeForce — гарантированы тормоза... а если создать OFFSCREEN_SURFACE + SYSTEM_MEMORY... то тормоза пропадают...
H_D>так что твой солюшн — не лучший...

Вот попробовал на Geforce4 c PIV-2Ггц.
==================================================================================
1000 Копирований из области системной памяти в primary размер обоих 640х480х16 бит
----------------------------------------------------------------------------------
BltFast 2,7 cек


копирование руками (ASM) 1,1 сек.
===================================================================================
Re[16]: еще один недостаток IDirectDrawSurfaceX
От: PavZ  
Дата: 11.07.03 06:34
Оценка:
Да еще один момент, не всегда можно создать так называемую WIDESURFACE т.е. с шириной большей чем Primary, даже с флагом DDSCAPS_SYSTEMMEMORY все зависит от видяхи.
С allocmem таких проблем нет.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.