Hope this is on-topic here as it's about a wgl function rather than
portable OpenGL code (if not, please can someone suggest a more
appropriate newsgroup?)
I was trying to code up a quick text renderer this evening using
wglUseFontBitmaps (as I've done a number of times in the past) and for
once it decided to be temperamental. (This despite the fact that pretty
much the exact same code worked fine elsewhere.) The code involved was this:
TextRenderer::TextRenderer(const std::string& typeface, int pointSize)
{
m_base = glGenLists(128);
HDC hdc = wglGetCurrentDC();
std::wstring ws(typeface.begin(), typeface.end());
m_pixelHeight = pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
HFONT font = CreateFont(-m_pixelHeight, 0, 0, 0, FW_NORMAL, false,
false, false, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY, DEFAULT_PITCH|FF_DONTCARE, ws.c_str());
HFONT oldFont = (HFONT)SelectObject(hdc, font);
bool succeeded = wglUseFontBitmaps(hdc, 32, 96, m_base+32) != 0;
SelectObject(hdc, oldFont);
DeleteFont(font);
if(!succeeded) throw Exception("<Whatever>");
#else
#error TextRenderer - Platform not yet supported.
#endif
}
Here wglUseFontBitmaps was returning false, but GetLastError(), which is
supposed to return additional error information, was returning 0 (i.e.
no error) when I added it in to check what was going on. (I also found
that the call succeeded if I constructed a TextRenderer object in
certain parts of the code base, but not others - note that the project's
single-threaded, so it's not a threading issue AFAICS. Also, replacing
the OpenGL rendering context via HGLRC hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc); made the call succeed but - naturally - messed
up everything else.) After some googling, I found that sometimes calling
wglUseFontBitmaps multiple times works when it fails the first time, but
no real explanation as to why that might be the case. Replacing the line
above with the loop below works, but I'm at a loss to explain what's
going on:
// Try and generate the font bitmaps - note that this sometimes has to
// be called multiple times to get it to work, which is seriously dodgy.
// If we fail several times in a row, just give up.
bool succeeded = false;
const int MAX_TRIES = 5;
for(int i=0; i<MAX_TRIES && !succeeded; ++i)
{
succeeded = wglUseFontBitmaps(hdc, 32, 96, m_base+32) != 0;
}
Any ideas as to what might be wrong please? Is it something I'm doing
wrong (99% chance!) or is it more likely to be an issue with the driver
implementation?
Cheers,
Stu
P.S. I know this whole approach to text rendering is sub-optimal (I
intend to replace it at a later date) - I'm just genuinely curious as to
what's going on at this point.
Are you sure you have a valid rendering context? (sounds like you dont).
jbw
I wondered that, but wglGetCurrentContext returns something non-NULL
when I put it in. Its documentation says:
"If the calling thread has a current OpenGL rendering context,
wglGetCurrentContext returns a handle to that rendering context.
Otherwise, the return value is NULL."
Also, the documentation for wglGetCurrentDC says:
"If the calling thread has a current OpenGL rendering context, the
function returns a handle to the device context associated with that
rendering context by means of the wglMakeCurrent function. Otherwise,
the return value is NULL."
If wglGetCurrentDC is giving me a valid (i.e. non-NULL) device context,
which it is, then that implies that the calling thread has a current
OpenGL rendering context. Also, wglGetCurrentDC is giving me the same
device context I get if I query SDL for the HWND of the window and call
GetDC on that - so I think I'm safe in saying that the device context is
valid, and hence the rendering context is as well.
This is what's puzzling me :) Along with the fact that calling
wglUseFontBitmaps twice can fail the first time and work the second
time. If the rendering context was invalid, you'd expect it to fail both
times surely?
Cheers,
Stu
yes, you would, unless the 1st pass causes a side-effect. Very strange
indeed.
jbw