How do I choose an accelerated pixel format under Windows?
Note: many consumer graphics cards cannot accelerate when the display is 24bpp, and many cannot accelerate when the desktop is at 32bpp in high-resolution. I always change to 800x600 x16bpp for my full-screen games. That ensures that the graphics card will have enough memory.
Normally, you call ChoosePixelFormat to choose a pixel format. But it's hard to know whether this will give you an accelerated pixel format. For us gamers, acceleration is the most important thing: we'd be happy to settle for a 16bpp accelerated surface, rather than a 32bpp unaccelerated surface.
The following code uses a gamer's heuristics to choose a suitable pixel format. Call it like this:
Code:
int bpp=-1; // don't care. (or a positive integer)
int depth=-1; // don't care. (or a positive integer)
int dbl=1; // we want double-buffering. (or -1 for 'don't care', or 0 for 'none')
int acc=1; // we want acceleration. (or -1 or 0)
int pf=ChoosePixelFormatEx(hdc,&bpp,&depth,&dbl,&acc);
The function will return, in those variables, the pixel format that it choose.
Code:
int ChoosePixelFormatEx(HDC hdc,int *p_bpp,int *p_depth,int *p_dbl,int *p_acc)
{ int wbpp; if (p_bpp==NULL) wbpp=-1; else wbpp=*p_bpp;
int wdepth; if (p_depth==NULL) wdepth=16; else wdepth=*p_depth;
int wdbl; if (p_dbl==NULL) wdbl=-1; else wdbl=*p_dbl;
int wacc; if (p_acc==NULL) wacc=1; else wacc=*p_acc;
PIXELFORMATDESCRIPTOR pfd; ZeroMemory(&pfd,sizeof(pfd)); pfd.nSize=sizeof(pfd); pfd.nVersion=1;
int num=DescribePixelFormat(hdc,1,sizeof(pfd),&pfd);
if (num==0) return 0;
unsigned int maxqual=0; int maxindex=0;
int max_bpp, max_depth, max_dbl, max_acc;
for (int i=1; i<=num; i++)
{ ZeroMemory(&pfd,sizeof(pfd)); pfd.nSize=sizeof(pfd); pfd.nVersion=1;
DescribePixelFormat(hdc,i,sizeof(pfd),&pfd);
int bpp=pfd.cColorBits;
int depth=pfd.cDepthBits;
bool pal=(pfd.iPixelType==PFD_TYPE_COLORINDEX);
bool mcd=((pfd.dwFlags & PFD_GENERIC_FORMAT) && (pfd.dwFlags & PFD_GENERIC_ACCELERATED));
bool soft=((pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED));
bool icd=(!(pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED));
bool opengl=(pfd.dwFlags & PFD_SUPPORT_OPENGL);
bool window=(pfd.dwFlags & PFD_DRAW_TO_WINDOW);
bool bitmap=(pfd.dwFlags & PFD_DRAW_TO_BITMAP);
bool dbuff=(pfd.dwFlags & PFD_DOUBLEBUFFER);
//
unsigned int q=0;
if (opengl && window) q=q+0x8000;
if (wdepth==-1 || (wdepth>0 && depth>0)) q=q+0x4000;
if (wdbl==-1 || (wdbl==0 && !dbuff) || (wdbl==1 && dbuff)) q=q+0x2000;
if (wacc==-1 || (wacc==0 && soft) || (wacc==1 && (mcd || icd))) q=q+0x1000;
if (mcd || icd) q=q+0x0040; if (icd) q=q+0x0002;
if (wbpp==-1 || (wbpp==bpp)) q=q+0x0800;
if (bpp>=16) q=q+0x0020; if (bpp==16) q=q+0x0008;
if (wdepth==-1 || (wdepth==depth)) q=q+0x0400;
if (depth>=16) q=q+0x0010; if (depth==16) q=q+0x0004;
if (!pal) q=q+0x0080;
if (bitmap) q=q+0x0001;
if (q>maxqual) {maxqual=q; maxindex=i;max_bpp=bpp; max_depth=depth; max_dbl=dbuff?1:0; max_acc=soft?0:1;}
}
if (maxindex==0) return maxindex;
if (p_bpp!=NULL) *p_bpp=max_bpp;
if (p_depth!=NULL) *p_depth=max_depth;
if (p_dbl!=NULL) *p_dbl=max_dbl;
if (p_acc!=NULL) *p_acc=max_acc;
return maxindex;
}
Bookmarks