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

  • Автор темы Guest
  • Дата начала
G

Guest

#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 и висит. Не знаю, что делать. Помогите, если кто-то знает!
 

DarkKnight

Well-known member
01.08.2010
653
0
#2
Тут мое мнение проблема только в том, что ты не создаешь главное окно и не регистрируешь его класс....
Но я могу правда и ошибаться, может при прямом доступе к видеопамяти (даже в Win) и не обязательно создавать окно, но я бы точно бы создал....
WNDCLASSEX Okno; //и пошел
...
..
.
//Класс, регстрция класса, создания окна класса, обработчик событий... Ну и твой код... И бесконечный цикл обаботки MSG Win...
Ну опять же говорю, что я могу и ошибаться, могу только тоно сказать, что DirectDraw - должен работать на сабзе Win-Application (из этого могу предположить, что должно быть хотя бы окно)
 

mibin

Well-known member
29.01.2009
48
0
#3
А вообще где ты определяешь сам директ икс? Помоему если я все правильно помню..сначало нужно определить то что ты работаешь с директоиксом каким а дирет дро это часть него уже
 

DarkKnight

Well-known member
01.08.2010
653
0
#4
Не, определено у него все правельно...
Хедер указан, lib присоединен... Так что доступ к DirectDraw он точно получает...
 

mibin

Well-known member
29.01.2009
48
0
#5
Попробуй создать с помощью DirectDrawCreateEx...
и добавь обработчик события на создание и на установку уровня взаимодействия, может интерфейс проблема раньше возникла
 

DarkKnight

Well-known member
01.08.2010
653
0
#6
Не, я проверял, этот участок кода у него точно работает, так как разрешение меняется и реально эксклюзив-доступ есть... А вот поверхность не хочет... Все равно думаю что оконное приложение должно быть... Лень проверить пока что...

IDirectDraw *dd;
HRESULT hdr = DirectDrawCreate (NULL, &dd, NULL);
dd->SetCooperativeLevel (NULL, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
dd->SetDisplayMode (800, 600, 8);
DDSURFACEDESC desc;
 
G

Guest

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

Guest

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

Guest

#10

lazybiz

Well-known member
03.11.2010
1 339
0
#11
А не структуру вряд ли получится.
Получится.

P. S. А зачем вообще писать typedef struct { ... } color; если можно struct color { ... };???
Для того, чтобы определить color как тип а не как переменную. Тебе же именно тип нужен был.
 

lazybiz

Well-known member
03.11.2010
1 339
0
#13
А не структуру вряд ли получится.
Сформулируй вопрос понятным образом, а то я могу не совсем точно понять о чем ты спрашиваешь.
С ходу я понял что структура, как ты думаешь, не подойдет для этого случая. Правильно я понял?

Но я же сказал - struct color { ... }; Это же тоже создаёт тип.
Это по-сути одно и то же. Просто я привык к такому синтаксису.
 

lazybiz

Well-known member
03.11.2010
1 339
0
#14
Партизан
Кстати, если использовать 4-х байтовый тип данных, то скорость записи в память возрастет; А если же ты будешь писать в 8-битном режиме то я могу тебе описать самый быстрый (какой только возможен на С) вариант.
 
G

Guest

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

lazybiz

Well-known member
03.11.2010
1 339
0
#16
И что это за вариант? Опишите, пожалуйста.
Этот случай актуален только при записи в 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;
}
 
G

Guest

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

lazybiz

Well-known member
03.11.2010
1 339
0
#18
Вот тебе наглядный пример работы. Если тебе и тут не совсем понятно, то уж извини.
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 );
}
Результат у меня выдал такой:
 

Вложения