<commit_before>#include <GL/glew.h>

#include <algorithm>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <sstream>

#include "GlScene.h"
#include "GlLayer.h"
#include "GlQuadTreeLODCalculator.h"
#include "GlBoundingBoxSceneVisitor.h"
#include "GlLODSceneVisitor.h"
#include "GlRect2D.h"
#include "GlShaderProgram.h"
#include "GlFrameBufferObject.h"
#include "Utils.h"
#include "GlGraph.h"
#include "TextureManager.h"

using namespace std;
using namespace tlp;

GlScene::GlScene() : _backgroundColor(255, 255, 255, 255), _clearBufferAtDraw(true), _sceneNeedRedraw(true),
  _backBufferTexture(0), _backBufferBackup(NULL), _pickingMode(false), _backupBackBuffer(true) {
  _lodCalculator = new GlQuadTreeLODCalculator();
  _lodCalculator->setRenderingEntitiesFlag(RenderingGlEntities);
  _mainLayer = new GlLayer("Main");
  addExistingLayer(_mainLayer);
  ostringstream oss;
  oss << "backBufferTexture" << reinterpret_cast<unsigned long>(this);
  _backBufferTextureName = oss.str();

}

GlScene::~GlScene() {

  for(vector<pair<string, GlLayer *> >::iterator it=_layersList.begin(); it!=_layersList.end(); ++it) {
    delete it->second;
  }

  delete _lodCalculator;
  delete [] _backBufferBackup;
}

void GlScene::setViewport(const Vec4i &viewport) {
  if (_viewport != viewport) {
    _viewport=viewport;
    _sceneNeedRedraw = true;
    if (_backupBackBuffer) {
      delete [] _backBufferBackup;
      _backBufferBackup = new unsigned char[viewport[2]*viewport[3]*4];
    }
  }
}

void GlScene::setViewport(int x, int y, int width, int height) {
  setViewport(Vec4i(x, y, width, height));
}

void GlScene::setBackgroundColor(const Color& color) {
  if (_backgroundColor != color) {
    _backgroundColor = color;
    _sceneNeedRedraw = true;
  }
}

void GlScene::initGlParameters(bool drawBackBufferBackup) {
  glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
  glScissor(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
  if (!drawBackBufferBackup) {
    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_STENCIL_TEST);
    glClearStencil(0xFF);
    glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    if (!_pickingMode) {
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    } else {
      glDisable(GL_BLEND);
    }
  }
}

void GlScene::requestDraw() {
  sendEvent(GlSceneEvent(GlSceneEvent::DRAW_REQUEST, this));
}

void GlScene::draw() {

  static BoundingBox lastSceneBoundingBox;
  BoundingBox sceneBoundingBox = getBoundingBox();
  if (lastSceneBoundingBox[0] != sceneBoundingBox[0] || lastSceneBoundingBox[1] != sceneBoundingBox[1]) {
    _lodCalculator->setSceneBoundingBox(sceneBoundingBox);
    lastSceneBoundingBox = sceneBoundingBox;
  }

  if (_sceneNeedRedraw || _pickingMode) {

    if (_clearBufferAtDraw) {
      if (!_pickingMode) {
        glClearColor(_backgroundColor.getRGL(), _backgroundColor.getGGL(), _backgroundColor.getBGL(), _backgroundColor.getAGL());
      } else {
        glClearColor(0.f, 0.f, 0.f, 0.f);
      }
      glClear(GL_COLOR_BUFFER_BIT);
    }

    initGlParameters();

    for(vector<pair<string, GlLayer *> >::iterator it=_layersList.begin(); it!=_layersList.end(); ++it) {
      glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      Camera &camera = *(it->second->getCamera());
      Light &light = *(it->second->getLight());
      GlLODSceneVisitor glLODSceneVisitor(_lodCalculator);
      it->second->acceptVisitor(&glLODSceneVisitor);
      camera.setViewport(_viewport);
      camera.initGl();
      if (!_pickingMode) {
        _lodCalculator->compute(&camera);
      } else {
        _lodCalculator->compute(&camera, _selectionViewport);
      }
      const vector<GlEntityLODUnit> &lodResult = _lodCalculator->getGlEntitiesResult(it->second);
      if (!lodResult.empty()) {
        for (size_t i = 0 ; i < lodResult.size() ; ++i) {
          if (lodResult[i].lod < 0 || !lodResult[i].glEntity->isVisible()) {
            continue;
          }
          glStencilFunc(GL_LEQUAL, lodResult[i].glEntity->getStencil(), 0xFF);
          lodResult[i].glEntity->draw(camera, light, _pickingMode);
        }
      }
    }

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_BLEND);
    glDisable(GL_SCISSOR_TEST);

    if (!_pickingMode && _backupBackBuffer && !GlFrameBufferObject::bufferBound()) {
      backupBackBuffer();
    }

  } else if (_backupBackBuffer) {
    initGlParameters(true);
    drawBackBufferBackup();
  }

  _sceneNeedRedraw = false;
}

void GlScene::backupBackBuffer() {
  if (_backBufferTexture == 0) {
    glGenTextures(1, &_backBufferTexture);
    glBindTexture(GL_TEXTURE_2D, _backBufferTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);
    TextureManager::instance()->addExternalTexture(_backBufferTextureName, _backBufferTexture);
  }
  glBindTexture(GL_TEXTURE_2D, _backBufferTexture);
#ifdef __EMSCRIPTEN__
  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _viewport[0], _viewport[1], _viewport[2], _viewport[3], 0);
#else
  // On desktop OpenGL, glCopyTexImage2D does not preserve antialiasing so we grab the back buffer content
  // and create a texture fro
  glReadBuffer(GL_BACK);
  glReadPixels(_viewport[0], _viewport[1], _viewport[2], _viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, _backBufferBackup);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _viewport[2], _viewport[3], 0, GL_RGBA, GL_UNSIGNED_BYTE, _backBufferBackup);
#endif
  glBindTexture(GL_TEXTURE_2D, 0);
  checkOpenGLError();
}

void GlScene::drawBackBufferBackup() {
  Camera camera2d(false);
  camera2d.setViewport(_viewport);
  camera2d.initGl();
  Vec2f bl(0, 0);
  Vec2f tr(_viewport[2], _viewport[3]);
  GlRect2D rect(bl, tr, 0, Color::White);
  rect.setTexture(_backBufferTextureName);
  rect.draw(camera2d);
}

GlLayer *GlScene::createLayer(const string &name, bool is3d) {
  GlLayer *oldLayer = getLayer(name);

  if(oldLayer != NULL) {
    warning() << "Warning : You have a layer in the scene with same name, previous layer will be removed" << endl;
    removeLayer(oldLayer);
  }

  GlLayer *newLayer = NULL;
  if (!is3d) {
    newLayer = new GlLayer(name, is3d);
  } else {
    newLayer = new GlLayer(name, getMainLayer()->getCamera(), getMainLayer()->getLight());
  }
  _layersList.push_back(pair<string,GlLayer*>(name, newLayer));<commit_msg>ensure stencil and depth buffers are cleared before drawing the back buffer texture<commit_after>#include <GL/glew.h>

#include <algorithm>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <sstream>

#include "GlScene.h"
#include "GlLayer.h"
#include "GlQuadTreeLODCalculator.h"
#include "GlBoundingBoxSceneVisitor.h"
#include "GlLODSceneVisitor.h"
#include "GlRect2D.h"
#include "GlShaderProgram.h"
#include "GlFrameBufferObject.h"
#include "Utils.h"
#include "GlGraph.h"
#include "TextureManager.h"

using namespace std;
using namespace tlp;

GlScene::GlScene() : _backgroundColor(255, 255, 255, 255), _clearBufferAtDraw(true), _sceneNeedRedraw(true),
  _backBufferTexture(0), _backBufferBackup(NULL), _pickingMode(false), _backupBackBuffer(true) {
  _lodCalculator = new GlQuadTreeLODCalculator();
  _lodCalculator->setRenderingEntitiesFlag(RenderingGlEntities);
  _mainLayer = new GlLayer("Main");
  addExistingLayer(_mainLayer);
  ostringstream oss;
  oss << "backBufferTexture" << reinterpret_cast<unsigned long>(this);
  _backBufferTextureName = oss.str();

}

GlScene::~GlScene() {

  for(vector<pair<string, GlLayer *> >::iterator it=_layersList.begin(); it!=_layersList.end(); ++it) {
    delete it->second;
  }

  delete _lodCalculator;
  delete [] _backBufferBackup;
}

void GlScene::setViewport(const Vec4i &viewport) {
  if (_viewport != viewport) {
    _viewport=viewport;
    _sceneNeedRedraw = true;
    if (_backupBackBuffer) {
      delete [] _backBufferBackup;
      _backBufferBackup = new unsigned char[viewport[2]*viewport[3]*4];
    }
  }
}

void GlScene::setViewport(int x, int y, int width, int height) {
  setViewport(Vec4i(x, y, width, height));
}

void GlScene::setBackgroundColor(const Color& color) {
  if (_backgroundColor != color) {
    _backgroundColor = color;
    _sceneNeedRedraw = true;
  }
}

void GlScene::initGlParameters(bool drawBackBufferBackup) {
  glViewport(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
  glScissor(_viewport[0], _viewport[1], _viewport[2], _viewport[3]);
  if (!drawBackBufferBackup) {
    glEnable(GL_SCISSOR_TEST);
    glEnable(GL_STENCIL_TEST);
    glClearStencil(0xFF);
    glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    if (!_pickingMode) {
      glEnable(GL_BLEND);
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    } else {
      glDisable(GL_BLEND);
    }
  }
}

void GlScene::requestDraw() {
  sendEvent(GlSceneEvent(GlSceneEvent::DRAW_REQUEST, this));
}

void GlScene::draw() {

  static BoundingBox lastSceneBoundingBox;
  BoundingBox sceneBoundingBox = getBoundingBox();
  if (lastSceneBoundingBox[0] != sceneBoundingBox[0] || lastSceneBoundingBox[1] != sceneBoundingBox[1]) {
    _lodCalculator->setSceneBoundingBox(sceneBoundingBox);
    lastSceneBoundingBox = sceneBoundingBox;
  }

  if (_sceneNeedRedraw || _pickingMode) {

    if (_clearBufferAtDraw) {
      if (!_pickingMode) {
        glClearColor(_backgroundColor.getRGL(), _backgroundColor.getGGL(), _backgroundColor.getBGL(), _backgroundColor.getAGL());
      } else {
        glClearColor(0.f, 0.f, 0.f, 0.f);
      }
      glClear(GL_COLOR_BUFFER_BIT);
    }

    initGlParameters();

    for(vector<pair<string, GlLayer *> >::iterator it=_layersList.begin(); it!=_layersList.end(); ++it) {
      glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      Camera &camera = *(it->second->getCamera());
      Light &light = *(it->second->getLight());
      GlLODSceneVisitor glLODSceneVisitor(_lodCalculator);
      it->second->acceptVisitor(&glLODSceneVisitor);
      camera.setViewport(_viewport);
      camera.initGl();
      if (!_pickingMode) {
        _lodCalculator->compute(&camera);
      } else {
        _lodCalculator->compute(&camera, _selectionViewport);
      }
      const vector<GlEntityLODUnit> &lodResult = _lodCalculator->getGlEntitiesResult(it->second);
      if (!lodResult.empty()) {
        for (size_t i = 0 ; i < lodResult.size() ; ++i) {
          if (lodResult[i].lod < 0 || !lodResult[i].glEntity->isVisible()) {
            continue;
          }
          glStencilFunc(GL_LEQUAL, lodResult[i].glEntity->getStencil(), 0xFF);
          lodResult[i].glEntity->draw(camera, light, _pickingMode);
        }
      }
    }

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_BLEND);
    glDisable(GL_SCISSOR_TEST);

    if (!_pickingMode && _backupBackBuffer && !GlFrameBufferObject::bufferBound()) {
      backupBackBuffer();
    }

  } else if (_backupBackBuffer) {
    initGlParameters(true);
    drawBackBufferBackup();
  }

  _sceneNeedRedraw = false;
}

void GlScene::backupBackBuffer() {
  if (_backBufferTexture == 0) {
    glGenTextures(1, &_backBufferTexture);
    glBindTexture(GL_TEXTURE_2D, _backBufferTexture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glBindTexture(GL_TEXTURE_2D, 0);
    TextureManager::instance()->addExternalTexture(_backBufferTextureName, _backBufferTexture);
  }
  glBindTexture(GL_TEXTURE_2D, _backBufferTexture);
#ifdef __EMSCRIPTEN__
  glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _viewport[0], _viewport[1], _viewport[2], _viewport[3], 0);
#else
  // On desktop OpenGL, glCopyTexImage2D does not preserve antialiasing so we grab the back buffer content
  // and create a texture fro
  glReadBuffer(GL_BACK);
  glReadPixels(_viewport[0], _viewport[1], _viewport[2], _viewport[3], GL_RGBA, GL_UNSIGNED_BYTE, _backBufferBackup);
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _viewport[2], _viewport[3], 0, GL_RGBA, GL_UNSIGNED_BYTE, _backBufferBackup);
#endif
  glBindTexture(GL_TEXTURE_2D, 0);
  checkOpenGLError();
}

void GlScene::drawBackBufferBackup() {
  glClear(GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  Camera camera2d(false);
  camera2d.setViewport(_viewport);
  camera2d.initGl();
  Vec2f bl(0, 0);
  Vec2f tr(_viewport[2], _viewport[3]);
  GlRect2D rect(bl, tr, 0, Color::White);
  rect.setTexture(_backBufferTextureName);
  rect.draw(camera2d);
}

GlLayer *GlScene::createLayer(const string &name, bool is3d) {
  GlLayer *oldLayer = getLayer(name);

  if(oldLayer != NULL) {
    warning() << "Warning : You have a layer in the scene with same name, previous layer will be removed" << endl;
    removeLayer(oldLayer);
  }

  GlLayer *newLayer = NULL;
  if (!is3d) {
    newLayer = new GlLayer(name, is3d);
  } else {
    newLayer = new GlLayer(name, getMainLayer()->getCamera(), getMainLayer()->getLight());
  }
  _layersList.push_back(pair<string,GlLayer*>(name, newLayer));
{'fraction_non_alphanumeric': 0.13065551739584888, 'fraction_numerical': 0.012692250261311034, 'mean_word_length': 4.911297440423654, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4910032', 'n_tokens_mistral': 4883, 'n_tokens_neox': 4719, 'n_words': 805}