Click to See Complete Forum and Search --> : 2d with direct3d: how to display argb data in a window


dcaro69
July 11th, 2007, 03:35 PM
Hey,

I have a rectangle (a piece of memory) that I fill with argb data. I would like to display it in a window, using direct3d. I have 3 questions about that.

1) I've read several tutorials. One solution would be to use the sprite interface. Then create a texture, fill it with data and render it onto the surface. I have written that code:


// the variable d contains a window and d3d object, device and sprite



d->device->Clear (0, NULL,
D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB (0, 0, 0, 0),
1.0f, 0);

d->device->BeginScene ();

// Here is my argb surface, named 'surf'

w = 64;
h = 64;
depth = 4;
pitch = depth * w;
surf = malloc (depth * w * h);
if (!surf) return 0;
ZeroMemory (surf, depth * w * h);

tmp = (unsigned char *)surf;
for (r = 0; r < w; r++) {
for (g = 0; g < h; g++, tmp += depth) {
tmp[0] = (r * 2 + foo) % 256;
tmp[1] = (g + foo) % 256;
tmp[2] = (w - 1 - g) * 4;
}
}
foo++;

rect.left = 0;
rect.top = 0;
rect.right = w;
rect.bottom = h;

// FIXME : other flags might speed up things
d->sprite->Begin (0);

d->device->CreateTexture (w, h, 0, 0,
D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT,
&texture, NULL);

// I have to fill the texture with the data of surf

d->sprite->SetTransform (&matrix);
d->sprite->Draw (texture, &rect, NULL, NULL, D3DCOLOR_ARGB (0, 0, 0, 0));
d->sprite->End ();

d->device->EndScene ();
d->device->Present (NULL, NULL, NULL, NULL);

As I mentioned in a comment of that code, I have to fill the texture with the surf data.

I've looked at a lot of tutorials, sites, etc... I didn't find any code to do that. I find code to fill a texture from a file, but not from a piece of memory.

So my first question is: is it possible, and if yes, how ?

2) My second question is about speed. My main cincern is speed. I've already written a code with directdraw 7. The speed is the same than a similar code on linux, using software routines. I don't know if it is normal or not. I wanted to get more speed, so I tried to do that with direct3d, in order to use hardware accelerated features of d3d.

With all the doc and tutorial I've read, I found several things to speed up all that stuff:

a) Using vertices instead of sprites
b) Using the immediate mode of d3d (see here (http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/dnardir3d/html/d3dim.asp))

Is it correct ? and if so, do you have some documentation about vertices or immediate mode, in order to achieve what I want ?

Also, if there are better solutions (that is, faster techniques related to d3d to do what I want), I would be pleased to know them

3) Finally, between opengl and d3d, is there a difference in speed ? (for what I want to do)

thank you very much

Vincent Torri

dcaro69
July 31st, 2007, 01:29 AM
I have looked at several tutorial, and I use a texture.

here is the code:

// g++ -g -Wall -o d3d d3d.cpp -ld3d9 -ld3dx9d
// with mpatrol :
// g++ -g -Wall -o d3d d3d.cpp -I/usr/local/include -L/usr/local/lib -ld3d9 -ld3dx9d -lmpatrol -lbfd -liberty -limagehlp

#include <cstdlib>
#include <cstdio>

#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#include <mpatrol.h>

typedef struct Data Data;

struct Data
{
LPDIRECT3D9 object;
LPDIRECT3DDEVICE9 device;
LPD3DXSPRITE sprite;
LPDIRECT3DTEXTURE9 texture;
int mask_r;
int mask_g;
int mask_b;
};


static LRESULT CALLBACK
MainWndProc(HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}

Data *
data_init (HWND window,
int width,
int height)
{
D3DPRESENT_PARAMETERS pp;
D3DDISPLAYMODE dm;
D3DSURFACE_DESC sd;
D3DCAPS9 caps;
Data *d;
DWORD flag;

printf ("init\n");

d = (Data *)malloc (sizeof (Data));
if (!d)
goto no_data;

d->object = Direct3DCreate9 (D3D_SDK_VERSION);
if (!d->object)
goto no_object;

if (FAILED (d->object->GetAdapterDisplayMode (D3DADAPTER_DEFAULT, &dm)))
goto no_device;

if (FAILED (d->object->GetDeviceCaps (D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
&caps)))
goto no_device;

flag = (caps.VertexProcessingCaps != 0)
? D3DCREATE_HARDWARE_VERTEXPROCESSING
: D3DCREATE_SOFTWARE_VERTEXPROCESSING;

ZeroMemory(&pp, sizeof(pp));
pp.BackBufferWidth = width;
pp.BackBufferHeight = height;
pp.BackBufferFormat = dm.Format;
pp.BackBufferCount = 1;
pp.SwapEffect = D3DSWAPEFFECT_FLIP;
pp.hDeviceWindow = window;
pp.Windowed = TRUE;

if (FAILED(d->object->CreateDevice (D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
window,
flag,
&pp,
&d->device)))
goto no_device;

if (FAILED (D3DXCreateSprite (d->device, &d->sprite)))
goto no_sprite;

if (FAILED (d->device->CreateTexture (width, height, 1,
D3DUSAGE_DYNAMIC,
dm.Format,
D3DPOOL_DEFAULT,
&d->texture, NULL)))
goto no_texture;

if (FAILED (d->texture->GetLevelDesc (0, &sd)))
goto no_level_desc;

switch (sd.Format) {
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
d->mask_r = 0x00ff0000;
d->mask_g = 0x0000ff00;
d->mask_b = 0x000000ff;
break;
case D3DFMT_R5G6B5:
d->mask_r = 0xf800;
d->mask_g = 0x07e0;
d->mask_b = 0x001f;
break;
default:
goto no_level_desc;
}

return d;

no_level_desc:
d->texture->Release ();
no_texture:
d->sprite->Release ();
no_sprite:
d->device->Release ();
no_device:
d->object->Release ();
no_object:
free (d);
no_data:
return NULL;
}

void
data_shutdown (Data *d)
{
if (!d)
return;

d->texture->Release ();
d->sprite->Release ();
d->device->Release ();
d->object->Release ();
// free (d);
}

void
data_paint (Data *d)
{
D3DLOCKED_RECT d3d_rect;
RECT rect;
int w;
int h;
int depth;
int pitch;
unsigned char *tmp;
unsigned char *d3d_tmp;
static int foo = 0;

void *surf;

w = 64;
h = 64;
depth = 4;
pitch = depth * w;

surf = calloc (w * h * depth, 1);
if (!surf) {
printf ("pas bon \n");
return;
}
tmp = (unsigned char *)surf;
for (int r = 0; r < w; r++) {
for (int g = 0; g < h; g++, tmp += depth) {
tmp[0] = (r * 2 + foo) % 256;
tmp[1] = (g + foo) % 256;
tmp[2] = (w - 1 - g) * 4;
}
}
foo++;

rect.left = 0;
rect.top = 0;
rect.right = w;
rect.bottom = h;

d->device->Clear (0, NULL, D3DCLEAR_TARGET,
D3DCOLOR_COLORVALUE(0.0f,1.0f,0.0f,1.0f), 1.0f, 0 );

if (FAILED (d->device->BeginScene ()))
return;

if (FAILED (d->sprite->Begin (0)))
return;
if (FAILED (d->texture->LockRect (0, &d3d_rect, NULL, D3DLOCK_DISCARD))) {
d->sprite->End ();
d->device->EndScene ();
return;
}

tmp = (unsigned char *)surf;
d3d_tmp = (unsigned char *)d3d_rect.pBits;
for (int j = 0; j < h; j++, tmp += pitch, d3d_tmp += d3d_rect.Pitch)
memcpy (d3d_tmp, tmp, pitch);

d->texture->UnlockRect(0);

d->sprite->Draw (d->texture, &rect, NULL, NULL,
D3DCOLOR_ARGB (0, 0, 0, 0));
d->sprite->End ();

d->device->EndScene ();
d->device->Present (NULL, NULL, NULL, NULL);

free (surf);
}

int WINAPI
WinMain(HINSTANCE hinstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
#if 0
main ()
#endif
{
WNDCLASS wc;
RECT rect;
MSG msg;
HINSTANCE instance;
HWND window;
Data *d;
int width;
int height;

instance = GetModuleHandle(0);
if (!instance)
goto no_instance;

ZeroMemory(&wc, sizeof(wc));
wc.lpfnWndProc = MainWndProc;
wc.hInstance = instance;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor (NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(1 + COLOR_BTNFACE);
wc.lpszClassName = "Direct3D_test";

if(!RegisterClass(&wc))
goto no_window_class;

width = 320;
height = 200;

rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
AdjustWindowRect (&rect, WS_OVERLAPPEDWINDOW | WS_SIZEBOX, FALSE);

window = CreateWindow("Direct3D_test",
"Direct3D_test",
WS_OVERLAPPEDWINDOW | WS_SIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top,
NULL, NULL, instance, NULL);
if (!window)
goto no_window;

d = data_init (window, width, height);
if (!d)
goto no_data;

ShowWindow(window, SW_SHOWDEFAULT);
UpdateWindow(window);

while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
data_paint (d);
}

data_shutdown (d);
DestroyWindow (window);
UnregisterClass ("Direct3D_test", instance);
FreeLibrary (instance);

return EXIT_SUCCESS;

no_data:
DestroyWindow (window);
no_window:
UnregisterClass ("Direct3D_test", instance);
no_window_class:
FreeLibrary (instance);
no_instance:
return EXIT_FAILURE;
}



it should display an animation in the top-left corner of the window, but nothing i drawn. I suspect that the initialization (data_init() function) is not good.

does someone see the problem ?

thank you