I am using OpenGL with Windows. How come when I use ChoosePixelFormat on a device context, ChoosePixelFormat returns a valid pixel format index, but SetPixelFormat fails on the exact same device context?
I used CreateCompatibleDC(0) to create my dc, then used CreateDIBitmap() to create a bitmap with the new DC, then selected bitmap into DC, then called ChoosePixelFormat(), then called SetPixelFormat(), which fails.
Here is my code (Delphi 5):
PROJECT SOURCE (OogleImageTest.dpr):
program OogleImageTest;
uses
//Forms,
OpenGL12,
Oogle in ‘…....\Units\Oogle.pas’,
OogleMisc in ‘…....\Units\OogleMisc.pas’;
{$R *.RES}
var
img: TOogleImage;
begin
InitOpenGL;
//Application.Initialize;
//Application.Run;
// If I change the next line to img := TOogleImage.Create; then the program works fine, but does not create a render context
img := TOogleRenderContext.Create;
try
finally
img.Free;
end;
end.
UNIT SOURCE (OogleMisc.pas):
unit OogleMisc;
interface
uses
Windows, OpenGL12
;
type
TOogleImage = class(TInterfacedObject)
protected
FDeviceContext: HDC;
FBitmap: HBITMAP;
FBitmapHeader: BITMAPINFOHEADER;
FPrevBitmap: HBITMAP;
public
constructor Create; virtual;
destructor Destroy; override;
end;
TOogleRenderContext = class(TOogleImage)
protected
FPixelFormat: PIXELFORMATDESCRIPTOR;
FPixelFormatIndex: Integer;
FRenderContext: HGLRC;
public
constructor Create; override;
destructor Destroy; override;
end;
implementation
uses
SysUtils
;
constructor TOogleImage.Create;
var
Unused: BITMAPINFO;
begin
FDeviceContext := CreateCompatibleDC(0);
if FDeviceContext = 0 then raise Exception.Create(‘Oogle image was unable to create a device context’);
with FBitmapHeader do begin
biSize := SizeOf(FBitmapHeader);
biWidth := 100;
biHeight := -100;
biPlanes := 1;
biBitCount := 16;
biCompression := BI_RGB;
end;
FBitmap := CreateDIBitmap(FDeviceContext, FBitmapHeader, CBM_INIT, nil, Unused, 0);
if FBitmap = 0 then raise Exception.Create('Oogle image was unable to create an internal device-independent bitmap');
FPrevBitmap := SelectObject(FDeviceContext, FBitmap);
end;
destructor TOogleImage.Destroy;
begin
try
if (FDeviceContext <> 0) and (FBitmap <> 0) then SelectObject(FDeviceContext, FPrevBitmap);
if FBitmap <> 0 then DeleteObject(FBitmap);
if FDeviceContext <> 0 then DeleteDC(FDeviceContext);
finally
inherited;
end;
end;
constructor TOogleRenderContext.Create;
const
BitDepth = 16;
ZBufferBitDepth = 16;
begin
inherited;
// Choose a pixel format to use when rendering to the device context
with FPixelFormat do begin
nSize := SizeOf(FPixelFormat);
nVersion := 1;
dwFlags := PFD_SUPPORT_OPENGL or PFD_DRAW_TO_BITMAP;
iPixelType := PFD_TYPE_RGBA;
cColorBits := BitDepth;
cDepthBits := ZBufferBitDepth;
iLayerType := PFD_MAIN_PLANE; // Ignored on recent implementations of OpenGL
end;
{$IFDEF OGLDEBUG}LogMsg('Choosing and setting a pixel format');{$ENDIF}
FPixelFormatIndex := ChoosePixelFormat(FDeviceContext, @FPixelFormat);
if FPixelFormatIndex = 0 then raise Exception.Create('Oogle render destination could not find a suitable matching pixel format for device context ' + IntToStr(FDeviceContext));
if not SetPixelFormat(FDeviceContext, FPixelFormatIndex, @FPixelFormat) then raise Exception.Create('Oogle render destination was unable to set rendering pixel format for device context ' + IntToStr(FDeviceContext));
FRenderContext := wglCreateContext(FDeviceContext);
if FRenderContext = 0 then raise Exception.Create('Oogle render context was unable to create an OpenGL render context');
if not wglMakeCurrent(FDeviceContext, FRenderContext) then raise Exception.Create('Oogle render context was unable to make its OpenGL render context the current context');
end;
destructor TOogleRenderContext.Destroy;
begin
try
if FRenderContext <> 0 then wglDeleteContext(FRenderContext);
finally
inherited;
end;
end;
end.