PDA

View Full Version : How to get HDC for back buffer



Jeff
02-19-2000, 02:13 PM
Hi,
I'm trying to use GDI function(ex BitBlt) at back buffer. However, I could not find any information about getting HDC for back buffer. When I call wglGetCurrentDC, it seems like I got DC for front buffer.

How can I get HDC for back buffer?

Any help will be appreciated.

Jeff

dmy
02-19-2000, 02:55 PM
i don't think it is possible.

however, note that these are my considerations about how opengl handles buffers: maybe it's not going this way.

i believe that when you create the association or a doublebuffered gl rendering context to a windows device context, you just tell opengl where to put framebuffer data it calculates.

opengl don't do a real pageflip, i mean the hardware pageflip where you change the start address register of the CRT processor.
opengl always do a blit, wich is fast, since it's accelerated by dedicate processors on the video card.
this scheme also allow specialized hardware to process the pixels while it transfers to the visible portion of the video ram: think about dithering from a 24-bit framebuffer to a 16-bit window.

the back buffer is really an offscreen buffer of the same size of your window.

i'm also interested in this... it would be very useful to have a opengl extension wich returns a pointer to framebuffer data DIRECTLY ON THE CARD, instead to have to make a copy to system ram with glCopyPixels()

Dolo/\/\ightY

Mad Max
02-25-2000, 11:00 AM
Try to use PFD_DRAW_TO_BITMAP.

DaveM
03-02-2000, 01:18 PM
I found these same things out by trial and error.

(1) HDC is only effective for window's visible front buffer.

(2) PFD_DRAW_TO_BITMAP will allow offscreen GDI manipulations, but everything will run slower due to MS generic OGL operating on system memory instead of acclerated ICD.

drumminj
03-26-2000, 08:15 AM
I'm trying to do the same thing as Jeff - render a graph in OGL and use bitblt to shift it over before rendering a new plot. Thus, the blt must be done on the back buffer. I've tried creating a rendering context for my memDC and rendering to that, then blt'ing from the memDC to the window DC. However, it doesn't appear any OGL rendering is happening. I'm guessing it has to do with the current rendering context, though I'm setting it with wglMakeCurrent(), which is returning without error, but I can't seem to figure out what the problem is. Any ideas?

A second note: I've tried doing the same thing completely in OGL using glCopyPixels() to shift the plots on the back buffer, but it seemed to run considerably slower than using GDI's BitBlt(). Does this sound right, or was there something else I'm missing that's probably slowing it down??

help/insight would be greatly appreciated

Jeff
03-27-2000, 11:40 PM
Hi,

I could not suceed in what I've been doing. Here is some info I found.

1. "You cannot get back buffer DC"
I found this article on MS site.

2. Most of people say "glCopyPixel is slower that GID Blit" and I read a book which says the same thing. So, your test is correct. OpenGL's pixel manipulation is terribly slow. I hope there should be some way for fast 2D rendering provided by VGA card vender or OpenGL itself or MS. Oh well.. I know OpenGL is for 3D though.

3. I also tried to find a example about using bitmap(memDC) for OpenGL rendering but I couldn't. There are some articles(also a book) which claims that you can use it but I need a working example. Is there anyone who got one?

I'm sorry I'm not helpful. well... I am also frustrated. I almost completed Stereoscopic 3D Quake3 wrapper but with this small problem I could not finish it.

I don't like say this but at least you're using Windows, and have to do high quality 2D graphics, you'd better use DirectX(DirectDraw). It has lots of 2D (fast) functions. I know it's not OpenGL's fault. MS should provide some ways for it for Windows programmer. Other OS too.

Good luck. :-)

Eric
03-28-2000, 03:55 AM
Hi !

Here is some code I use in my application to have OGL rendering into an offscreen bitmap and then copy the result into a dialog box custom button (Preview Button !).

I am sorry but for security reasons, I had to change the code and I haven't tested the result (no time). I hope it still works....

Post messages for any question regarding the code...

Eric

P.S. : you should start at the function called RenderToDC and follow it (I always code from top to bottom where the most interesting function is at the bottom !).

P.S. 2 : well at least, this code compiles (but didn't test it !).

//--------------------------------------------------------------------//

#include <stdafx.h>

HGLRC InitializeOpenGL(CDC*& pDC,DWORD PixelFormatFlags);
bool SetupPixelFormat(CDC*& hDC,DWORD PixelFormatFlags);
bool SetupViewingFrustum(int Width,int Height);
void EnterPictureMode(int Width,int Height);
void* SnapPicture(void);
void ExitPictureMode(void);
bool CreateOffScreenDC(CDC*& pDC);
void* CreateOffScreenBitmap(CDC*& pDC,HBITMAP& pBitmap,int Width,int Height);
void RENDER_WHATEVER_YOU_WANT(void);

// You need some variables //

bool m_Perspective;
double m_oLeft,m_oRight;
double m_oBottom,m_oTop;
double m_oNear,m_oFar;
double m_pFOV,m_pAspect;
double m_pZNear,m_pZFar;

CDC *m_pPictureDC;
HGLRC m_hPictureRC;
HBITMAP m_hPictureBitmap;
void *m_PictureDIBits;
int PictureWidth,PictureHeight;


// Give it a pDC and your settings, it gives tou a HGLRC ! //

HGLRC InitializeOpenGL(CDC*& pDC,DWORD PixelFormatFlags)
{

HGLRC hRC;

if (!SetupPixelFormat(pDC,PixelFormatFlags))
{
AfxMessageBox("SetupPixelFormat failed.\n");
return 0;
}
if ((hRC=wglCreateContext(pDC->GetSafeHdc()))==0)
{
AfxMessageBox("wglCreateContext failed.");
return 0;
}
if (wglMakeCurrent(pDC->GetSafeHdc(),hRC)==FALSE)
{
AfxMessageBox("wglMakeCurrent failed.");
return 0;
}
return hRC;

}

// The classic one ! //

bool SetupPixelFormat(CDC*& pDC,DWORD PixelFormatFlags)
{

#define N_Color_Bits 32
#define N_ZBuffer_Bits 24

PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),// size of this pfd
1, // version number
PixelFormatFlags,
PFD_TYPE_RGBA, // RGBA type
N_Color_Bits, // Color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
N_ZBuffer_Bits, // Z-Buffer Depth
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};

int pixelformat;
PIXELFORMATDESCRIPTOR *pPFD=&pfd;

if ((pixelformat=ChoosePixelFormat(pDC->GetSafeHdc(),pPFD))==0)
{
AfxMessageBox("ChoosePixelFormat failed.");
return false;
}
if (SetPixelFormat(pDC->GetSafeHdc(),pixelformat,pPFD)==FALSE)
{
AfxMessageBox("SetPixelFormat failed.");
return false;
}

return true;
}

// Another Classic ! //

bool SetupViewingFrustum(int Width,int Height)
{

if (m_Perspective)
gluPerspective(m_pFOV,(GLdouble) Width/Height*m_pAspect,m_pZNear,m_pZFar);
else
glOrtho(m_oLeft,m_oRight,m_oBottom,m_oTop,m_oNear, m_oFar);
if (glGetError()!= GL_NO_ERROR)
{
//AfxMessageBox("Error while trying to set viewing frustum.");
return false;
}
return true;

}

// Creates an OffScreen DC compatible with current Display //

bool CreateOffScreenDC(CDC*& pDC)
{

pDC=new CDC;
if (pDC->CreateCompatibleDC(NULL)==0) // failure to get DC
{
AfxMessageBox("Couldn't get a valid DC.");
return false;
}

}

// Give it your pDC and Width/Height, it gives you the Bitmap ! //

void* CreateOffScreenBitmap(CDC*& pDC,HBITMAP& pBitmap,int Width,int Height)
{

void *DIBits;
BYTE myBufferInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
BITMAPINFO *myBitmapInfo = (BITMAPINFO *) myBufferInfo;

myBitmapInfo->bmiHeader.biSize = sizeof(myBitmapInfo->bmiHeader);
myBitmapInfo->bmiHeader.biWidth = Width;
myBitmapInfo->bmiHeader.biHeight = Height;
myBitmapInfo->bmiHeader.biPlanes = 1;
myBitmapInfo->bmiHeader.biBitCount = N_Color_Bits;
myBitmapInfo->bmiHeader.biCompression = BI_RGB;
myBitmapInfo->bmiHeader.biSizeImage = Width*Height*N_Color_Bits/8;
pBitmap=CreateDIBSection(pDC->GetSafeHdc(),myBitmapInfo,DIB_RGB_COLORS,&DIBits,NULL,0);
if (pBitmap==NULL)
{
AfxMessageBox("Couldn't get a valid Bitmap");
return 0;
}
pDC->SelectObject(pBitmap);
return(DIBits);

}

// Start the snapshot process ! //

void EnterPictureMode(int Width,int Height)
{

PictureWidth=Width;
PictureHeight=Height;
CreateOffScreenDC(m_pPictureDC);
m_PictureDIBits=CreateOffScreenBitmap(m_pPictureDC ,m_hPictureBitmap,PictureWidth,PictureHeight);
m_hPictureRC=InitializeOpenGL(m_pPictureDC,PFD_DRA W_TO_BITMAP|PFD_SUPPORT_OPENGL);
glViewport(0,0,PictureWidth,PictureHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SetupViewingFrustum(PictureWidth,PictureHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

}

void* SnapPicture(void)
{

wglMakeCurrent(m_pPictureDC->GetSafeHdc(),m_hPictureRC);

RENDER_WHATEVER_YOU_WANT();

wglMakeCurrent(NULL,NULL);
return(m_PictureDIBits);

}

// Start the snapshot process ! //

void ExitPictureMode(void)
{

wglDeleteContext(m_hPictureRC);
m_pPictureDC->DeleteDC();
delete m_pPictureDC;
DeleteObject(m_hPictureBitmap);

}


void RenderToDC(CDC *pDC,int Width,int Height)
{

void *DIBits;
BYTE myBufferInfo[sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD)];
BITMAPINFO *myBitmapInfo = (BITMAPINFO *) myBufferInfo;


EnterPictureMode(Width,Height);
DIBits=SnapPicture();
StretchDIBits(pDC->GetSafeHdc(),0,0,Width,Height,0,0,Width,Height,DIB its,myBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
ExitPictureMode();

}

//--------------------------------------------------------------------//

drumminj
04-02-2000, 09:20 PM
Eric -

Thank you for posting code. I believe I am doing the same thing as you, however, It still does nto appear that anything is being rendered to the offscreen bitmap. The program for which I am doing this is quite complex, so I will post only the GL-relevant code.

-------------------------------------------

I am using this function to initialize openGL:

void EnableOpenGL(HDC *hdc, HGLRC *hrc )
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;

// set the pixel format for the DC
ZeroMemory( &pfd, sizeof( pfd ) );
pfd.nSize = sizeof( pfd );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_BITMAP |
PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat( *hdc, &pfd );
SetPixelFormat( *hdc, iFormat, &pfd );

// create and enable the render context (RC)
*hrc = wglCreateContext( *hdc );
iFormat = wglMakeCurrent( *hdc, *hrc );
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}

-------------------------------------------

I create my offscreen device context and rendering context using the following, where hdc is a handle to the device context of the main window:

memDC = CreateCompatibleDC(hdc);
EnableOpenGL(&memDC, &memRC);
glViewport(0,0,xSize, ySize);
// set up a projection matrix to fill the client window
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // init the projection matrix

// set up orthographic projection
gluOrtho2D(0, xSize,0, ySize);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();


And then create the off-screen bitmap:

memDCBitmap = CreateCompatibleBitmap(hdc,xSize,ySize);
SelectObject(memDC,memDCBitmap);

where the dimensions of the program window are xSize by ySize. I then perform my rendering, and blit from the off-screen bitmap to the window device context w/ the following:

BitBlt(hdc,0,0,xSize,ySize,memDC,0,0,SRCCOPY);


I know for certain that the problem is not with the bliting from the off-screen device context to the window device context because everything works perfectly if I use GDI drawing functions instead of openGL. All of the wgl functions return successfully, so I really have no clue where my problem lies. Do you see anything here or have any ideas?

thanks

J

Eric
04-02-2000, 10:30 PM
Hi !

I think your problem is this call to CreateCompatibleBitmap...

If you look at my CreateOffscreenBitmap function, I create a DIB with CreateDIBSection instead of a DDB with CreateOffscreenBitmap...

The PFD_DRAW_TO_BITMAP flag enables OpenGL to render to a MEMORY bitmap which is a DIB and not a DDB.

So I think you should try using a DIB instead of a DDB (as far as I remember, this is the reason why my program did not work in its early stages...)

Eric

P.S. : as you can see in my function, the problem with creating a DIB is that you have to specify a BITMAPINFO. But you can steal this from the code above and change the bits you want to change !!!

Eric
04-02-2000, 10:32 PM
Hum, made a mistake : you should read :

"instead of a DDB created with CreateCompatibleBitmap"....

Sorry for that !

Eric

drumminj
04-03-2000, 09:28 AM
I see. Thanks. I guess I'm a little confused why OGL won't render to a device dependent bitmap. I'm not very well-versed in the difference between the two, but I don't understand why OGL would distinguish. Can you explain?

thanks again

drumminj
04-03-2000, 09:53 AM
Oh, and btw - that did work http://www.opengl.org/discussion_boards/ubb/smile.gif