PDA

View Full Version : blitting problem from 8 bit off-screen to 32 bit primary



anubis79
18-01-2004, 03:59 PM
At the end I've created a Directdraw object and surfaces. Now please look at these codes. They use DelphiX header but a question will come for you


var
Form1: TForm1;
TDDR: IDirectDraw; // temporary interface to query IDirectDraw7
DDR: IDirectDraw7; // DirectDraw object
PS: IDirectDrawSurface7; // a Primary Surface
OSS: IDirectDrawSurface7; // an off-screen surface
SD: TDDSurfaceDesc2; // Surface description
Bitmap: TBitmap;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('your bmp');

DirectX.DirectDrawCreate(nil, TDDR, nil);
TDDR.QueryInterface(DirectX.IID_IDirectDraw7, DDR); // look for IDirectDraw7
TDDR := nil; // now we don't need it. Because we have DDR from IDirectDraw7

DDR.SetCooperativeLevel(Form1.Handle, DirectX.DDSCL_NORMAL); // sharing desktop
{and we don't describe a Display Mode so GDI's Display mode is valid}

FillChar(SD, Sizeof(TDDSurfaceDesc2), 0);
SD.dwSize := Sizeof(TDDSurfaceDesc2);
SD.dwFlags := DirectX.DDSD_CAPS;
SD.ddsCaps.dwCaps := DirectX.DDSCAPS_PRIMARYSURFACE;

DDR.CreateSurface(SD, PS, nil); // we get a described primary surface

FillChar(SD, Sizeof(TDDSurfaceDesc2), 0); // planning an off-screen surface
SD.dwSize := Sizeof(TDDSurfaceDesc2);
SD.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
SD.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;
SD.dwHeight := Bitmap.Height;
SD.dwWidth := Bitmap.Width;

DDR.CreateSurface(SD, OSS, nil); // have an off-screen surface

end;

procedure TForm1.Button1Click(Sender: TObject);
var
Can: TCanvas;
VDC: HDC;
begin
Can := TCanvas.Create;
OSS.GetDC(VDC); // capture an DC for using a var Canvas (Can)
Can.Handle := VDC; // using the same memory
Can.Draw(0, 0, Bitmap);
OSS.ReleaseDC(VDC); // After drawing release must be called.
PS.BltFast(Form1.ClientOrigin.X,Form1.ClientOrigin .Y, OSS, Bitmap.Canvas.ClipRect, DDBLTFAST_WAIT);
Can.Handle := 0;
Can.Free;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Bitmap.Free;
end;If you compile it you will see your bmp on the form. My aim was to create an independent off-screen which not get the same BPP with Primary Surface. To realize it add DDSD_PIXELFORMAT to the dwFlags and after SD.dwWidth := Bitmap.Width add SD.ddpfPixelFormat.dwRGBBitCount := 8; and code will be changed like this:var
Form1: TForm1;
TDDR: IDirectDraw; // temporary interface to query IDirectDraw7
DDR: IDirectDraw7; // DirectDraw object
PS: IDirectDrawSurface7; // a Primary Surface
OSS: IDirectDrawSurface7; // an off-screen surface
SD: TDDSurfaceDesc2; // Surface description
Bitmap: TBitmap;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
Bitmap := TBitmap.Create;
Bitmap.LoadFromFile('your bmp');

DirectX.DirectDrawCreate(nil, TDDR, nil);
TDDR.QueryInterface(DirectX.IID_IDirectDraw7, DDR); // look for IDirectDraw7
TDDR := nil; // now we don't need it. Because we have DDR from IDirectDraw7

DDR.SetCooperativeLevel(Form1.Handle, DirectX.DDSCL_NORMAL); // sharing desktop
{and we don't describe a Display Mode so GDI's Display mode is valid}

FillChar(SD, Sizeof(TDDSurfaceDesc2), 0);
SD.dwSize := Sizeof(TDDSurfaceDesc2);
SD.dwFlags := DirectX.DDSD_CAPS;
SD.ddsCaps.dwCaps := DirectX.DDSCAPS_PRIMARYSURFACE;

DDR.CreateSurface(SD, PS, nil); // we get a described primary surface

FillChar(SD, Sizeof(TDDSurfaceDesc2), 0); // planning an off-screen surface
SD.dwSize := Sizeof(TDDSurfaceDesc2);
SD.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH or DDSD_PIXELFORMAT;
SD.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN;
SD.dwHeight := Bitmap.Height;
SD.dwWidth := Bitmap.Width;
SD.ddpfPixelFormat.dwRGBBitCount := 8;

DDR.CreateSurface(SD, OSS, nil); // have an off-screen surface

end;

procedure TForm1.Button1Click(Sender: TObject);
var
Can: TCanvas;
VDC: HDC;
begin
Can := TCanvas.Create;
OSS.GetDC(VDC); // capture an DC for using a var Canvas (Can)
Can.Handle := VDC; // using the same memory
Can.Draw(0, 0, Bitmap);
OSS.ReleaseDC(VDC); // After drawing release must be called.
PS.BltFast(Form1.ClientOrigin.X,Form1.ClientOrigin .Y, OSS, Bitmap.Canvas.ClipRect, DDBLTFAST_WAIT);
Can.Handle := 0;
Can.Free;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Bitmap.Free;
end;
When you compile and click the button1 you will have an exception. Why?I need your helps. What is the problem with it? Please give some advice about it.

Clootie
20-01-2004, 07:59 PM
This works:
// SD.ddpfPixelFormat.dwSize := SizeOf(SD.ddpfPixelFormat);
SD.ddpfPixelFormat.dwFlags := DDPF_RGB;
SD.ddpfPixelFormat.dwRGBBitCount := 32;
SD.ddpfPixelFormat.dwRBitMask := $FF0000;
SD.ddpfPixelFormat.dwGBitMask := $FF00;
SD.ddpfPixelFormat.dwBBitMask := $FF;
// SD.ddpfPixelFormat.dwRGBAlphaBitMask := $FF000000;

anubis79
21-01-2004, 12:29 PM
Thank you. It works. But do you think off-screen surface bitcount is 8 bit. Your code: SD.ddpfPixelFormat.dwRGBBitCount := 32; and after bitmasks it will be 8 bit? Why do I want an 8 bit offscreen and 32 bit primary? Because of two reasons:

1) My image is 8 bit and I want to put it in an 8 bit off-screen or backbuffer. And then view it in GDI (of course with an 32 bit primary)

2) For a faster blitting and high FPS. As you know blitting from 8 bit surface to 32 bit primary is faster than blitting from 32 bit surface to 32 bit primary. And I want to use this trick. But I'm still don't sure is it possible under DirectX.

I've looked for it on the web but I don't find any resources. Could you possibly give me some idea about my project if you have?

Clootie
21-01-2004, 07:28 PM
SD.ddpfPixelFormat.dwFlags := DDPF_PALETTEINDEXED8;