void OrthoDoDraw()

in layer1/Ortho.cpp [1489:1956]


void OrthoDoDraw(PyMOLGlobals * G, int render_mode)
{
  COrtho *I = G->Ortho;
  CGO *orthoCGO = NULL;
  int x, y;
  int l, lcount;
  char *str;
  int showLines;
  int height;
  int overlay, text;
  int rightSceneMargin;
  int internal_feedback;
  int times = 1, origtimes = 0;
  int double_pump = false;
  const float *bg_color;
  int skip_prompt = 0;
  int render = false;
  int internal_gui_mode = SettingGetGlobal_i(G, cSetting_internal_gui_mode);
  int generate_shader_cgo = 0;

  I->RenderMode = render_mode;
  if(SettingGetGlobal_b(G, cSetting_seq_view)) {
    SeqUpdate(G);
    I->HaveSeqViewer = true;
  } else if(I->HaveSeqViewer) {
    SeqUpdate(G);
    I->HaveSeqViewer = false;
  }

  if(SettingGet_i(G, NULL, NULL, cSetting_internal_prompt))
    skip_prompt = 0;
  else
    skip_prompt = 1;

  double_pump = SettingGet_i(G, NULL, NULL, cSetting_stereo_double_pump_mono);
  bg_color = ColorGet(G, SettingGet_color(G, NULL, NULL, cSetting_bg_rgb));

  I->OverlayColor[0] = 1.0F - bg_color[0];
  I->OverlayColor[1] = 1.0F - bg_color[1];
  I->OverlayColor[2] = 1.0F - bg_color[2];
  if(diff3f(I->OverlayColor, bg_color) < 0.25)
    zero3f(I->OverlayColor);

  PRINTFD(G, FB_Ortho)
    " OrthoDoDraw: entered.\n" ENDFD;
  if(G->HaveGUI && G->ValidContext) {

#ifdef GL_FRAMEBUFFER_UNDEFINED
    // prevents GL_INVALID_FRAMEBUFFER_OPERATION (0x0506) on macOS
    // with external Monitor
    if (glCheckFramebufferStatus &&
        glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_UNDEFINED)
      return;
#endif

    if(Feedback(G, FB_OpenGL, FB_Debugging))
      PyMOLCheckOpenGLErr("OrthoDoDraw checkpoint 0");

    if(SettingGetGlobal_b(G, cSetting_internal_gui)) {
      switch (SettingGetGlobal_i(G, cSetting_internal_gui_mode)) {
      case 0:
        rightSceneMargin = DIP2PIXEL(SettingGetGlobal_i(G, cSetting_internal_gui_width));
        break;
      default:
        rightSceneMargin = 0;
        break;
      }
    } else {
      rightSceneMargin = 0;
    }

    internal_feedback = SettingGetGlobal_i(G, cSetting_internal_feedback);

    overlay = OrthoGetOverlayStatus(G);
    switch (overlay) {
    case -1:                   /* auto overlay */
      overlay = I->CurLine - I->AutoOverlayStopLine;
      if(overlay < 0) {
        overlay += (OrthoSaveLines + 1);
      }
      if(internal_feedback > 1) {
        overlay -= (internal_feedback - 1);
      }
      if(overlay < 0)
        overlay = 0;
      break;
    case 1:                    /* default -- user overlay_lines */
      overlay = SettingGetGlobal_i(G, cSetting_overlay_lines);
      break;
    }

    text = SettingGetGlobal_b(G, cSetting_text);
    if(text)
      overlay = 0;

    if(overlay || (!text))
      if(!SceneRenderCached(G))
        render = true;

    if(render_mode < 2) {
      if(SceneMustDrawBoth(G)) {
        OrthoDrawBuffer(G, GL_BACK_LEFT);
        SceneGLClear(G, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        OrthoDrawBuffer(G, GL_BACK_RIGHT);
        SceneGLClear(G, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        times = 2;
        double_pump = true;
      } else {
        OrthoDrawBuffer(G, GL_BACK);
        SceneGLClear(G, GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        times = 1;
        double_pump = false;
      }
    } else {
      times = 1;
      double_pump = false;
    }

    I->DrawTime = -I->LastDraw;
    I->LastDraw = UtilGetSeconds(G);
    I->DrawTime += I->LastDraw;
    ButModeSetRate(G, (float) I->DrawTime);

    if(render && (render_mode < 2))
      SceneRender(G, NULL, 0, 0, NULL, 0, 0, 0,
                  SettingGetGlobal_b(G, cSetting_image_copy_always));
    else if (text){
      bg_grad(G);  // only render the background for text
    }
    SceneGLClearColor(0.0, 0.0, 0.0, 1.0);

    origtimes = times;
    while(times--) {

      switch (times) {
      case 1:
        OrthoDrawBuffer(G, GL_BACK_LEFT);

        break;
      case 0:
        if(double_pump) {
          OrthoDrawBuffer(G, GL_BACK_RIGHT);
        } else
          OrthoDrawBuffer(G, GL_BACK);
        break;
      }

      OrthoPushMatrix(G);

      if (G->ShaderMgr->ShadersPresent()){
	if(SettingGetGlobal_b(G, cSetting_internal_gui) && 
	   SettingGetGlobal_b(G, cSetting_use_shaders)){
	  CGO *orthoFastCGO = CGONew(G);
	    CGOFree(I->orthoFastCGO);
	  if (I->Blocks->recursiveFastDraw(orthoFastCGO)){
	    int ok = true;
	    CGO *expandedCGO;
	    CGOStop(orthoFastCGO);
	    expandedCGO = CGOExpandDrawTextures(orthoFastCGO, 0);
	    CHECKOK(ok, expandedCGO);
	    if (ok)
	      I->orthoFastCGO = CGOOptimizeScreenTexturesAndPolygons(expandedCGO, 0);
	    CHECKOK(ok, I->orthoFastCGO);
	    CGOFree(orthoFastCGO);
	    CGOFree(expandedCGO);
	  } else {
	    CGOFree(orthoFastCGO);
	  }
	  if (!I->orthoCGO){
	    orthoCGO = CGONew(G);
	    generate_shader_cgo = true;
	  } else {
	    OrthoRenderCGO(G);
	    OrthoPopMatrix(G);
	    continue;
	  }
	}
      }
      x = I->X;
      y = I->Y;

      if(I->DrawText && internal_feedback) {    /* moved to avoid conflict with menus */
        Block *block = SceneGetBlock(G);
        height = block->rect.bottom;
        switch (internal_gui_mode) {
        case 0:
	  if (generate_shader_cgo){
	    CGOColor(orthoCGO, 0.f, 0.f, 0.f);
	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	    CGOVertex(orthoCGO, I->Width - rightSceneMargin, height - 1, 0.f);
	    CGOVertex(orthoCGO, I->Width - rightSceneMargin, 0, 0.f);
	    CGOVertex(orthoCGO, 0.f, height - 1,0.f);
	    CGOVertex(orthoCGO, 0.f, 0.f, 0.f);
	    CGOEnd(orthoCGO);
	  } else {
	    glColor3f(0.0, 0.0, 0.0);
	    glBegin(GL_POLYGON);
	    glVertex2i(I->Width - rightSceneMargin, height - 1);
	    glVertex2i(I->Width - rightSceneMargin, 0);
	    glVertex2i(0, 0);
	    glVertex2i(0, height - 1);
	    glEnd();
	  }
          /* deliberate fall-through */
        case 1:
	  if (generate_shader_cgo){
	    CGOColor(orthoCGO, 0.3f, 0.3f, 0.3f);
	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	    CGOVertex(orthoCGO, 1 + I->Width - rightSceneMargin, height, 0.f);
	    CGOVertex(orthoCGO, 1 + I->Width - rightSceneMargin, height - 1, 0.f);
	    CGOVertex(orthoCGO, -1, height, 0.f);
	    CGOVertex(orthoCGO, -1, height - 1, 0.f);
	    CGOEnd(orthoCGO);
	  } else {
	    glColor3f(0.3, 0.3, 0.3);
	    glBegin(GL_LINES);
	    glVertex2i(1 + I->Width - rightSceneMargin, height - 1);
	    glVertex2i(-1, height - 1);
	    glEnd();
	  }
          break;
        }
      }

      PRINTFD(G, FB_Ortho)
        " OrthoDoDraw: drawing blocks...\n" ENDFD;

      if(SettingGetGlobal_b(G, cSetting_internal_gui)) {
        int internal_gui_width = DIP2PIXEL(SettingGetGlobal_i(G, cSetting_internal_gui_width));
        if(internal_gui_mode != 2) {
	  if (generate_shader_cgo){
	    CGOColor(orthoCGO, 0.3f, 0.3f, 0.3f);
	    CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	    CGOVertex(orthoCGO, I->Width - internal_gui_width, 0.f, 0.f);
	    CGOVertex(orthoCGO, I->Width - internal_gui_width + 1.f, 0.f, 0.f);
	    CGOVertex(orthoCGO, I->Width - internal_gui_width, I->Height, 0.f);
	    CGOVertex(orthoCGO, I->Width - internal_gui_width + 1.f, I->Height, 0.f);
	    CGOEnd(orthoCGO);
	  } else {
	    glColor3f(0.3, 0.3, 0.3);
	    glBegin(GL_LINES);
	    glVertex2i(I->Width - internal_gui_width, 0);
	    glVertex2i(I->Width - internal_gui_width, I->Height);
	    glEnd();
	  }
        }
      }

      OrthoRestorePrompt(G);

      if(I->DrawText) {
        int adjust_at = 0;
        /* now print the text */

        lcount = 0;
        x = cOrthoLeftMargin;
        y = cOrthoBottomMargin + MovieGetPanelHeight(G);

#ifdef _PYMOL_SHARP3D
        if(SceneGetStereo(G) && SettingGetGlobal_b(G, cSetting_overlay)) {
          y += (7 * cOrthoLineHeight) / 10;
        }
#endif
        if(SettingGetGlobal_b(G, cSetting_text) || I->SplashFlag)
          showLines = I->ShowLines;
        else {
          showLines = internal_feedback + overlay;
        }
        if(internal_feedback)
          adjust_at = internal_feedback + 1;

        l = (I->CurLine - (lcount + skip_prompt)) & OrthoSaveLines;

	if (orthoCGO)
	  CGOColorv(orthoCGO, I->TextColor);
	else
	  glColor3fv(I->TextColor);

        while(l >= 0) {
          lcount++;
          if(lcount > showLines)
            break;
          if(lcount == adjust_at)
            y += 4;
          str = I->Line[l & OrthoSaveLines];
          if(internal_gui_mode) {
            TextSetColor(G, I->OverlayColor);
          } else if(strncmp(str, I->Prompt, 6) == 0) {
            if(lcount < adjust_at)
              TextSetColor(G, I->TextColor);
            else {
              if(length3f(I->OverlayColor) < 0.5)
                TextSetColor(G, I->OverlayColor);
              else
                TextSetColor(G, I->TextColor);
            }
          } else
            TextSetColor(G, I->OverlayColor);
          TextSetPos2i(G, x, y);
          if(str) {
            TextDrawStr(G, str ORTHOCGOARGVAR);
            if((lcount == 1) && (I->InputFlag)) {
              if(!skip_prompt) {
                if(I->CursorChar >= 0) {
                  TextSetPos2i(G, x + cOrthoCharWidth * I->CursorChar, y);
                }
                TextDrawChar(G, '_' ORTHOCGOARGVAR);
              }
            }
          }
          l = (I->CurLine - (lcount + skip_prompt)) & OrthoSaveLines;
          y = y + cOrthoLineHeight;
        }
      }

      OrthoDrawWizardPrompt(G ORTHOCGOARGVAR);

      if(SettingGetGlobal_b(G, cSetting_text) || I->SplashFlag) {
        Block *block;
        int active_tmp;
        block = SeqGetBlock(G);
        active_tmp = block->active;
        block->active = false;
        I->Blocks->recursiveDraw(orthoCGO);
        block->active = active_tmp;
      } else {
        I->Blocks->recursiveDraw(orthoCGO);
      }

      PRINTFD(G, FB_Ortho)
        " OrthoDoDraw: blocks drawn.\n" ENDFD;

      if(I->LoopFlag) {
        const float *vc = ColorGet(G, cColorFront);
	if (generate_shader_cgo){
	  CGOColor(orthoCGO, vc[0], vc[1], vc[2]);

	  CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.top+1, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.left+1, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.left+1, I->LoopRect.top+1, 0.f);
	  CGOEnd(orthoCGO);
	  CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.top, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.top+1, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.top, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.top+1, 0.f);
	  CGOEnd(orthoCGO);
	  CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.top+1, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right+1, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right+1, I->LoopRect.top+1, 0.f);
	  CGOEnd(orthoCGO);
	  CGOBegin(orthoCGO, GL_TRIANGLE_STRIP);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.left, I->LoopRect.bottom+1, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.bottom, 0.f);
	  CGOVertex(orthoCGO, I->LoopRect.right, I->LoopRect.bottom+1, 0.f);
	  CGOEnd(orthoCGO);
	} else {
	  glColor3f(vc[0], vc[1], vc[2]);
	  glBegin(GL_LINE_LOOP);
	  glVertex2i(I->LoopRect.left, I->LoopRect.top);
	  glVertex2i(I->LoopRect.right, I->LoopRect.top);
	  glVertex2i(I->LoopRect.right, I->LoopRect.bottom);
	  glVertex2i(I->LoopRect.left, I->LoopRect.bottom);
	  glVertex2i(I->LoopRect.left, I->LoopRect.top);
	  glEnd();
	}
      }


      /* BEGIN PROPRIETARY CODE SEGMENT (see disclaimer in "os_proprietary.h") */
#ifdef PYMOL_EVAL
      OrthoDrawEvalMessage(G ORTHOCGOARGVAR);
#endif
#ifdef PYMOL_BETA
      OrthoDrawBetaMessage(G);
#endif
#ifdef JYMOL_EVAL
      OrthoDrawEvalMessage(G);
#endif
#ifdef PYMOL_EDU
      OrthoDrawEduMessage(G);
#endif
#ifdef PYMOL_COLL
      OrthoDrawCollMessage(G);
#endif
#ifdef AXPYMOL_EVAL
      OrthoDrawAxMessage(G);
#endif

      /* END PROPRIETARY CODE SEGMENT */

      OrthoPopMatrix(G);

      if(Feedback(G, FB_OpenGL, FB_Debugging))
        PyMOLCheckOpenGLErr("OrthoDoDraw final checkpoint");

    }                           /* while */

  }

  if (generate_shader_cgo){
    int ok = true;

    {
#ifdef SHOW_FONT_TEXTURE
      /*  This shows the font texture in the middle of the screen, we might want to debug it */
      CGO *testOrthoCGO =  orthoCGO;
      //      CGO *testOrthoCGO =  CGONew(G);
      float minx = 100.f, maxx = 612.f, miny = 100.f, maxy = 612.f;
      short texcoord = true;
      CGOAlpha(testOrthoCGO, .5f);
      CGOColor(testOrthoCGO, 0.f, 0.f, 0.f);
      CGOBegin(testOrthoCGO, GL_TRIANGLE_STRIP);
      if (texcoord)
	CGOTexCoord2f(testOrthoCGO, 1.f, 1.f);
      CGOVertex(testOrthoCGO, maxx, maxy, 0.f);
      if (texcoord)
	CGOTexCoord2f(testOrthoCGO, 1.f, 0.f);
      CGOVertex(testOrthoCGO, maxx, miny, 0.f);
      if (texcoord)
	CGOTexCoord2f(testOrthoCGO, 0.f, 1.f);
      CGOVertex(testOrthoCGO, minx, maxy, 0.f);
      if (texcoord)
	CGOTexCoord2f(testOrthoCGO, 0.f, 0.f);
      CGOVertex(testOrthoCGO, minx, miny, 0.f);
      CGOEnd(testOrthoCGO);
      CGOStop(testOrthoCGO);
#else
    CGOStop(orthoCGO);
#endif
    }
    {
      CGO *expandedCGO = CGOExpandDrawTextures(orthoCGO, 0);
      CHECKOK(ok, expandedCGO);
      if (ok)
	I->orthoCGO = CGOOptimizeScreenTexturesAndPolygons(expandedCGO, 0);
      CGOFree(orthoCGO);
      CGOFree(expandedCGO);
      
      while(origtimes--){
	switch (origtimes){
	case 1:
	  OrthoDrawBuffer(G, GL_BACK_LEFT);
	  break;
	case 0:
	  if(double_pump) {
	    OrthoDrawBuffer(G, GL_BACK_RIGHT);
	  } else
	    OrthoDrawBuffer(G, GL_BACK);
	  break;
	}
	OrthoPushMatrix(G);
	OrthoRenderCGO(G);
	OrthoPopMatrix(G);
      }
    }
  }

  I->DirtyFlag = false;
  PRINTFD(G, FB_Ortho)
    " OrthoDoDraw: leaving...\n" ENDFD;

}