I am making an application that has a bunch of small windows and controls in it (2D rendering), and I would like to render each window and control to its own bitmap. This is wha
OpenGL contexts must be created matching the target device context. For windows they're created in a different way than for bitmaps. See
http://msdn.microsoft.com/en-us/library/windows/desktop/dd368826(v=vs.85).aspx notably the dwFlags
, where there are among others
PFD_DRAW_TO_WINDOW The buffer can draw to a window or device surface.
PFD_DRAW_TO_BITMAP The buffer can draw to a memory bitmap.
However you shouldn rush ahead and create a render context for your DIB DC. Why? Because it will be slow as hell, as OpenGL render contexts on a DIB section will use a software rasterizer supporting only OpenGL-1.1 running on the CPU.
Instead you should create a Framebuffer Object, attach a color renderbuffer attachment and when finished to a glReadPixels
into your DIBSection. Much easier, much faster.
(I have no idea why StackOverflow doesn't get the syntax coloring right, i.e. figuring out where's a comment and where not)
// flushes the OpenGL error queue and
// counts the total number of errors
int flushGLErrors(void)
{
int i = 0;
while( glGetError() != GL_NO_ERROR ) {
i++;
}
return i;
}
// returns a HBITMAP or NULL.
// The HBITMAP must be freed using DeleteObject
HBITMAP ReadPixelsToHBITMAP(
int x,
int y,
int width,
int height )
{
void *pdata = NULL;
/* Note that this values only makes sense if we know a target
* output size like if we put the image to paper. */
const int physical_resolution = 2835; /* 72 DPI */
BITMAPINFOHEADER bmih = {
/* .biSize = */ sizeof(bmih),
/* .biWidth = */ width,
/* .bi.Height = */ height,
/* .biPlanes = */ 1, /* mandatory */
/* .biBitCount = */ 24, /* 8 bits per pixel */
/* .biCompression = */ BI_RGB, /* uncompressed */
/* .biSizeImage = */ 0, /* implicit */
/* .biXPelsPerMeter = */ physical_resolution, /* ignored */
/* .biYPelsPerMeter = */ physical_resolution, /* ignored */
/* .biClrUsed = */ 0, /* no palette */
/* .biClrImportant = */ 0
};
HBITMAP hbm = CreateDIBSection(
hdc, /* may be different than the DC used for OpenGL */
(PBITMAPINFO)&bmih, /* can do this cast, because no palette is used */
DIB_RGB_COLORS,
&pdata,
NULL,
0
);
if( !hbm ) {
return NULL;
}
flushGLErrors();
glPixelStorei(GL_PACK_SWAP_BYTES, GL_FALSE);
glPixelStorei(GL_PACK_LSB_FIRST, GL_TRUE);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
if( glGetError() != GL_NO_ERROR ) {
DeleteObject(hbm);
return NULL;
}
glReadPixels(x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, pdata);
if( glGetError() != GL_NO_ERROR ) {
DeleteObject(hbm);
return NULL;
}
return hbm;
}