protected void runLoop() {
    if (!created.get()) {
      throw new IllegalStateException();
    }

    if (pbuffer.isBufferLost()) {
      pbuffer.destroy();

      try {
        pbuffer = new Pbuffer(width, height, pixelFormat, null);
        pbuffer.makeCurrent();

        // Context MUST be reset here to avoid invalid objects!
        renderer.invalidateState();
      } catch (LWJGLException ex) {
        listener.handleError("Failed to restore pbuffer content", ex);
      }
    }

    listener.update();
    checkGLError();

    renderer.postFrame();

    // Need to flush GL commands
    // to see any result on the pbuffer's front buffer.
    GL11.glFlush();

    int frameRate = settings.getFrameRate();
    if (frameRate >= 1) {
      Display.sync(frameRate);
    }
  }
  private void render(
      final List<? extends Spatial> toDrawA,
      final Spatial toDrawB,
      final Scene toDrawC,
      final List<Texture> texs,
      final int clear) {
    try {
      if (_pbuffer == null || _pbuffer.isBufferLost()) {
        if (_pbuffer != null && _pbuffer.isBufferLost()) {
          logger.warning("PBuffer contents lost - will recreate the buffer");
          deactivate();
          _pbuffer.destroy();
        }
        initPbuffer();
      }

      if (texs.size() == 1
          && _useDirectRender
          && !texs.get(0).getTextureStoreFormat().isDepthFormat()) {
        // setup and render directly to a 2d texture.
        LwjglTextureStateUtil.doTextureBind(texs.get(0), 0, true);
        activate();
        switchCameraIn(clear);
        _pbuffer.releaseTexImage(Pbuffer.FRONT_LEFT_BUFFER);

        if (toDrawA != null) {
          doDraw(toDrawA);
        } else {
          doDraw(toDrawB);
        }

        switchCameraOut();

        deactivate();
        _pbuffer.bindTexImage(Pbuffer.FRONT_LEFT_BUFFER);
      } else {
        // render and copy to a texture
        activate();
        switchCameraIn(clear);

        if (toDrawA != null) {
          doDraw(toDrawA);
        } else {
          doDraw(toDrawB);
        }

        switchCameraOut();

        for (int i = 0; i < texs.size(); i++) {
          copyToTexture(texs.get(i), 0, 0, _width, _height, 0, 0);
        }

        deactivate();
      }

    } catch (final Exception e) {
      logger.logp(
          Level.SEVERE, this.getClass().toString(), "render(Spatial, Texture)", "Exception", e);
    }
  }
  private void initPbuffer() {

    try {
      if (_pbuffer != null) {
        giveBackContext();
        ContextManager.removeContext(_pbuffer);
      }
      final PixelFormat format =
          new PixelFormat(
                  _settings.getAlphaBits(), _settings.getDepthBits(), _settings.getStencilBits())
              .withSamples(_settings.getSamples())
              .withBitsPerPixel(_settings.getColorDepth())
              .withStereo(_settings.isStereo());
      _pbuffer = new Pbuffer(_width, _height, format, _texture, null);
      final Object contextKey = _pbuffer;
      try {
        _pbuffer.makeCurrent();
      } catch (final LWJGLException e) {
        throw new RuntimeException(e);
      }

      final LwjglContextCapabilities caps =
          new LwjglContextCapabilities(GLContext.getCapabilities());
      ContextManager.addContext(
          contextKey, new RenderContext(contextKey, caps, ContextManager.getCurrentContext()));

    } catch (final Exception e) {
      logger.logp(Level.SEVERE, this.getClass().toString(), "initPbuffer()", "Exception", e);

      if (_texture != null && _useDirectRender) {
        logger.warning(
            "Your card claims to support Render to Texture but fails to enact it.  Updating your driver might solve this problem.");
        logger.warning("Attempting to fall back to Copy Texture.");
        _texture = null;
        _useDirectRender = false;
        initPbuffer();
        return;
      }

      logger.log(Level.WARNING, "Failed to create Pbuffer.", e);
      return;
    }

    try {
      activate();

      _width = _pbuffer.getWidth();
      _height = _pbuffer.getHeight();

      deactivate();
    } catch (final Exception e) {
      logger.log(Level.WARNING, "Failed to initialize created Pbuffer.", e);
      return;
    }
  }
 public void setMultipleTargets(final boolean force) {
   if (force) {
     logger.fine("Copy Texture Pbuffer used!");
     _useDirectRender = false;
     _texture = null;
     if (_pbuffer != null) {
       try {
         giveBackContext();
       } catch (final LWJGLException ex) {
       }
       ContextManager.removeContext(_pbuffer);
     }
   } else {
     if ((Pbuffer.getCapabilities() & Pbuffer.RENDER_TEXTURE_SUPPORTED) != 0) {
       logger.fine("Render to Texture Pbuffer supported!");
       if (_texture == null) {
         logger.fine("No RenderTexture used in init, falling back to Copy Texture PBuffer.");
         _useDirectRender = false;
       } else {
         _useDirectRender = true;
       }
     } else {
       logger.fine("Copy Texture Pbuffer supported!");
       _texture = null;
     }
   }
 }
  private void activate() {
    if (_active == 0) {
      try {
        _oldContext = ContextManager.getCurrentContext();
        _pbuffer.makeCurrent();

        ContextManager.switchContext(_pbuffer);

        ContextManager.getCurrentContext().clearEnforcedStates();
        ContextManager.getCurrentContext().enforceStates(_enforcedStates);

        if (_bgColorDirty) {
          GL11.glClearColor(
              _backgroundColor.getRed(),
              _backgroundColor.getGreen(),
              _backgroundColor.getBlue(),
              _backgroundColor.getAlpha());
          _bgColorDirty = false;
        }
      } catch (final LWJGLException e) {
        logger.logp(Level.SEVERE, this.getClass().toString(), "activate()", "Exception", e);
        throw new Ardor3dException();
      }
    }
    _active++;
  }
  protected void deinitInThread() {
    renderable.set(false);

    listener.destroy();
    renderer.cleanup();
    pbuffer.destroy();
    logger.fine("Offscreen buffer destroyed.");

    super.internalDestroy();
  }
  protected void initInThread() {
    if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
      logger.severe("Offscreen surfaces are not supported.");
      return;
    }

    int samples = getNumSamplesToUse();
    pixelFormat =
        new PixelFormat(
            settings.getBitsPerPixel(),
            0,
            settings.getDepthBits(),
            settings.getStencilBits(),
            samples);

    width = settings.getWidth();
    height = settings.getHeight();
    try {
      Thread.setDefaultUncaughtExceptionHandler(
          new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread thread, Throwable thrown) {
              listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
            }
          });

      pbuffer = new Pbuffer(width, height, pixelFormat, null, null, createContextAttribs());
      pbuffer.makeCurrent();

      renderable.set(true);

      logger.fine("Offscreen buffer created.");
      printContextInitInfo();
    } catch (LWJGLException ex) {
      listener.handleError("Failed to create display", ex);
    } finally {
      // TODO: It is possible to avoid "Failed to find pixel format"
      // error here by creating a default display.
    }
    super.internalCreate();
    listener.initialize();
  }
  protected int determineMaxSamples(int requestedSamples) {
    boolean displayWasCurrent = false;
    try {
      // If we already have a valid context, determine samples using current
      // context.
      if (Display.isCreated() && Display.isCurrent()) {
        if (GLContext.getCapabilities().GL_ARB_framebuffer_object) {
          return GL11.glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES);
        } else if (GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
          return GL11.glGetInteger(EXTFramebufferMultisample.GL_MAX_SAMPLES_EXT);
        }
        // Doesn't support any of the needed extensions .. continue down.
        displayWasCurrent = true;
      }
    } catch (LWJGLException ex) {
      listener.handleError("Failed to check if display is current", ex);
    }

    if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
      // No pbuffer, assume everything is supported.
      return Integer.MAX_VALUE;
    } else {
      Pbuffer pb = null;

      if (!displayWasCurrent) {
        // OpenGL2 method: Create pbuffer and query samples
        // from GL_ARB_framebuffer_object or GL_EXT_framebuffer_multisample.
        try {
          pb = new Pbuffer(1, 1, new PixelFormat(0, 0, 0), null);
          pb.makeCurrent();

          if (GLContext.getCapabilities().GL_ARB_framebuffer_object) {
            return GL11.glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES);
          } else if (GLContext.getCapabilities().GL_EXT_framebuffer_multisample) {
            return GL11.glGetInteger(EXTFramebufferMultisample.GL_MAX_SAMPLES_EXT);
          }

          // OpenGL2 method failed.
        } catch (LWJGLException ex) {
          // Something else failed.
          return Integer.MAX_VALUE;
        } finally {
          if (pb != null) {
            pb.destroy();
            pb = null;
          }
        }
      }

      // OpenGL1 method (DOESNT WORK RIGHT NOW ..)
      requestedSamples = FastMath.nearestPowerOfTwo(requestedSamples);
      try {
        requestedSamples = Integer.MAX_VALUE;
        /*
        while (requestedSamples > 1) {
            try {
                pb = new Pbuffer(1, 1, new PixelFormat(16, 0, 8, 0, requestedSamples), null);
            } catch (LWJGLException ex) {
                if (ex.getMessage().startsWith("Failed to find ARB pixel format")) {
                    // Unsupported format, so continue.
                    requestedSamples = FastMath.nearestPowerOfTwo(requestedSamples / 2);
                } else {
                    // Something else went wrong ..
                    return Integer.MAX_VALUE;
                }
            } finally {
                if (pb != null){
                    pb.destroy();
                    pb = null;
                }
            }
        }*/
      } finally {
        if (displayWasCurrent) {
          try {
            Display.makeCurrent();
          } catch (LWJGLException ex) {
            listener.handleError("Failed to make display current after checking samples", ex);
          }
        }
      }

      return requestedSamples;
    }
  }
 public void cleanup() {
   ContextManager.removeContext(_pbuffer);
   _pbuffer.destroy();
 }