   wxGLCanvas and double-buffering
  I'm working on a very-very-legacy app written in C++, with Python and WXWidgets handling the UI. One of the UI elements is a wxGLCanvas histogram of the pixels in a camera view, with some text indicating the mean/max/median values and the floor and ceiling cutoffs. The histogram itself is drawn using OpenGL calls, while the text is drawn with wxPaintDC::DrawText calls.As part of fitting more camera views onto the screen at one time, we bought a new display, with the intent of rotating it 90 degrees (so it'd be ~1200x1900 instead of the other way around). Unfortunately, we discovered that when we do that, the text in the histogram flickers like crazy, rapidly causing our users to go insane.After some debugging, I determined that the canvas object was not double-buffered; it's not clear to me why it wasn't flickering all the time because of this. I assume that rotating the display switched us to a lower display refresh rate or something. I added WX_GL_DOUBLEBUFFER to the parameters passed to the wxGLCanvas, and the flicker went away...but now the histogram colors are dark-red-on-black, instead of the black-on-white they're supposed to be. What's more, changing the colors used by the OpenGL calls has no effect. Note that the color of the drawn text is unchanged; it's just the background of the canvas, and the histogram itself, that have gone nuts. It doesn't look like an RGB-BGA type of issue either (i.e. color rotation) because the saturation and brightness of the histogram have changed.I've also determined that using GLUT's glutBitmapCharacter instead of the DrawText calls will result in zero flicker, but it also causes irregular crashes; somehow the OnPaint method of the canvas object is getting called on an invalid object, so the first time we try to access a member field, we get a segfault.I've included the relevant code below. If you have any ideas what might be wrong, I'd love to hear them. I apologize for the styling; one of my many long-term projects is to clean all this up.// Code where we create the GLHistogram instances:int glParams[] = {WX_GL_DOUBLEBUFFER};for(int camID=0;camID<NCAMS;camID++){  m_histPlotWin[camID] = new GLHistogram(this, ID_WIN_HIST+camID, (1<<BITS_PER_PIXEL), NULL, glParams);}// GLHistogram codeGLHistogram::GLHistogram(wxWindow *parent, wxWindowID id, int histSize, GLViewer *vie, int* glParams) :wxGLCanvas(parent, id, wxDefaultPosition, wxSize(100,100), 0, _T("GLHisto"), glParams),  maxRight(histSize-1),  viewer(vie),  m_histogramData( new wxUint16[histSize] ){  m_init   = FALSE;  m_gllist = 0;  dragging = 0;  m_log = false;  left =   0;  right = 678;  leftMap = 350;  rightMap = 450;  histogram_displayed = NULL;  ResetStats();  m_pMenuPopup = new wxMenu;  m_pMenuPopup->Append(Menu1_Recalc, _T("&Recalc"));  m_pMenuPopup->Append(Menu1_ZoomContrast, _T("zoom to braces"));  m_pMenuPopup->Append(Menu1_ZoomFull, _T("&zoom full"));  m_pMenuPopup->Append(Menu1_ZoomMinMax, _T("zoom &fit"));  m_pMenuPopup->Append(Menu1_Log, _T("&logarithm"));  SetCursor(*wxCROSS_CURSOR);}bool GLHistogram::InitGL(){  GetSize(&w,&h);  wxCHECK2(w>0, return false);//Linux  wxCHECK2(h>0, return false);//Linux    range = right - left;  rangePerPixel = double(range)/w;  leftMap_displayed  = int( (leftMap - left)  / rangePerPixel );  rightMap_displayed = int( (rightMap - left) / rangePerPixel );  histogram_displayed = new int[w];  glViewport(0, 0, (GLint) w, (GLint) h);    glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glOrtho(  0, w-1, 0, h-1, -1,1);  glMatrixMode(GL_MODELVIEW);    glEnable(GL_TEXTURE_2D);  glClearColor(1.0, 1.0, 1.0, 0.0);  return m_init = TRUE;}// Function stolen from the GLUT example at// http://www.opengl.org/resources/features/fontsurveyvoid GLHistogram::print_bitmap_string(char* str, double x, double y) {  glRasterPos2f(x, y);  if (str && strlen(str)) {    while (*str) { glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *str); str++;    }  }}void GLHistogram::OnPaint( wxPaintEvent& event ){    // This is a dummy, to avoid an endless succession of paint messages.    // OnPaint handlers must always create a wxPaintDC.    wxPaintDC dc(this);#ifndef __WXMOTIF__  if (!GetContext()) return;#endif    if (GetParent()->IsShown()) SetCurrent(); if (!m_init)    {    if( !InitGL() ) return;    }  // Sets up the 'p' array of histogram values.  // Doesn't actually draw anything.  generateDisplayedHistogram();  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // actual histogram:  glColor3f(0.0, 0.0, 0.0);  //NOFILL glBegin(GL_LINE_STRIP);  glBegin(GL_LINES);  int *p = histogram_displayed;  double fac = histogram_displayed_max>1? ( double(h-20) / (m_log ? log(histogram_displayed_max+1.0) : histogram_displayed_max ) )  //2003Jun06: +1.0 for '1 count to show > 0' !!!!    : 1;  for(int x=0;x<w;x++)    {    const int y = *p++;    glVertex2f(x, 0);    glVertex2f(x, (m_log? log(y+1.0)*fac :y*fac)); //2003Jun06: +1.0 for '1 count to show > 0' !!!!    }  glEnd();  // leftMap - rightMap - brackets  glColor3f(1.0, 0.0, 0.0);  glBegin(GL_LINE_STRIP);// Specify verticies in quad    glVertex2i(leftMap_displayed+5, 7);    glVertex2i(leftMap_displayed,   7);    glVertex2i(leftMap_displayed,   h-7);    glVertex2i(leftMap_displayed+5, h-7);  glEnd();  glBegin(GL_LINE_STRIP);    // Specify verticies in quad    glVertex2i(rightMap_displayed-5, 7);    glVertex2i(rightMap_displayed,   7);    glVertex2i(rightMap_displayed,   h-7);    glVertex2i(rightMap_displayed-5, h-7);  glEnd();    // mean idicator  int mean_displayed = int( (m_histavg - left) / rangePerPixel );  int yy = 7+ h/4;  //printf("%d %f %d %f\n", mean_displayed,m_histavg, left, rangePerPixel );  glColor3f(0.0, 1.0, 0.0);  glBegin(GL_LINES);    glVertex2i(mean_displayed-1, 7);    glVertex2i(mean_displayed-1, yy);    glVertex2i(mean_displayed  , 4);    glVertex2i(mean_displayed  , yy+3);    glVertex2i(mean_displayed+1, 7);    glVertex2i(mean_displayed+1, yy);  glEnd();    //const int baseLineOffset = wxGetApp().getImgBaseLineOffset();  // TODO: Better string handling  //Non-flickering text, but crashes after running for awhile.  //const int leftSpacer = 10;  //const int betweenSpacer = 10;  //char str1[20], str2[10], str3[30];  //sprintf(str1, "%5d [ %5d", leftMap - baseLineOffset, m_histmin - baseLineOffset);  //glColor3f(0.0, 0.0, 1.0);  //print_bitmap_string(str1, leftSpacer, 45);  //sprintf(str2, "%5d", m_histpeak - baseLineOffset);  //glColor3f(1.0, 0.0, 0.0);  //print_bitmap_string(str2, leftSpacer + betweenSpacer + strlen(str1) * 8, 45);  //sprintf(str3, "%5d ] %5d %s", m_histmax - baseLineOffset, rightMap - baseLineOffset, m_log ? "(log)" : "");  //glColor3f(0.0, 0.0, 1.0);  //print_bitmap_string(str3, leftSpacer + betweenSpacer * 2 + (strlen(str1) + strlen(str2)) * 8, 45);  glFlush();  SwapBuffers();  glFinish(); //20060417 http://glprogramming.com/red/appendixc.html - Synchronizing Executionconst int baseLineOffset= wxGetApp().getImgBaseLineOffset(); //20060322 dc.SetTextForeground(*wxBLUE);   // Non-crashing, flickers-unless-double-buffered textwxString s1 = wxString::Format(_T("%d [ %d"),   leftMap-baseLineOffset, m_histmin-baseLineOffset);wxString s2 = wxString::Format(_T("%d"), m_histpeak-baseLineOffset);wxString s3 = wxString::Format(_T("%d ] %d %s"),    m_histmax-baseLineOffset, rightMap-baseLineOffset, m_log?_T("(log)"):_T(""));  dc.DrawText(s1, 10, 5);dc.SetTextForeground(*wxRED);  dc.DrawText(s2, 10-10 + s1.length()*8, 5); // guessed offsets for windowsdc.SetTextForeground(*wxBLUE);  dc.DrawText(s3, 10+0 + (s1.length()+s2.length())*8, 5);}