protected void runTestGL(
      final GLCapabilities caps,
      final FrameLayout frameLayout,
      final boolean twoCanvas,
      final boolean resizeByComp)
      throws InterruptedException, InvocationTargetException {
    final JFrame frame = new JFrame("Bug816: " + this.getTestMethodName());
    Assert.assertNotNull(frame);
    final Container framePane = frame.getContentPane();

    final GLCanvas glCanvas1 = new GLCanvas(caps);
    Assert.assertNotNull(glCanvas1);
    final GLCanvas glCanvas2;
    if (twoCanvas) {
      glCanvas2 = new GLCanvas(caps);
      Assert.assertNotNull(glCanvas2);
    } else {
      glCanvas2 = null;
    }

    final Dimension glcDim = new Dimension(width / 2, height);
    final Dimension frameDim = new Dimension(twoCanvas ? width + 64 : width / 2 + 64, height + 64);

    setComponentSize(null, glCanvas1, glcDim, glCanvas2, glcDim);

    switch (frameLayout) {
      case None:
        {
          framePane.add(glCanvas1);
        }
        break;
      case Flow:
        {
          final Container c = new Container();
          c.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
          c.add(glCanvas1);
          if (twoCanvas) {
            c.add(glCanvas2);
          }
          framePane.add(c);
        }
        break;
      case DoubleBorderCenterSurrounded:
        {
          final Container c = new Container();
          c.setLayout(new BorderLayout());
          c.add(new Button("north"), BorderLayout.NORTH);
          c.add(new Button("south"), BorderLayout.SOUTH);
          c.add(new Button("east"), BorderLayout.EAST);
          c.add(new Button("west"), BorderLayout.WEST);
          if (twoCanvas) {
            final Container c2 = new Container();
            c2.setLayout(new GridLayout(1, 2));
            c2.add(glCanvas1);
            c2.add(glCanvas2);
            c.add(c2, BorderLayout.CENTER);
          } else {
            c.add(glCanvas1, BorderLayout.CENTER);
          }
          framePane.setLayout(new BorderLayout());
          framePane.add(new Button("NORTH"), BorderLayout.NORTH);
          framePane.add(new Button("SOUTH"), BorderLayout.SOUTH);
          framePane.add(new Button("EAST"), BorderLayout.EAST);
          framePane.add(new Button("WEST"), BorderLayout.WEST);
          framePane.add(c, BorderLayout.CENTER);
        }
        break;
      case Box:
        {
          final Container c = new Container();
          c.setLayout(new BoxLayout(c, BoxLayout.X_AXIS));
          c.add(glCanvas1);
          if (twoCanvas) {
            c.add(glCanvas2);
          }
          framePane.add(c);
        }
        break;
      case Split:
        {
          final Dimension sbDim = new Dimension(16, 16);
          final JScrollPane vsp =
              new JScrollPane(
                  ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                  ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
          {
            final JScrollBar vsb = vsp.getVerticalScrollBar();
            vsb.setPreferredSize(sbDim);
            final BoundedRangeModel model = vsb.getModel();
            model.setMinimum(0);
            model.setMaximum(100);
            model.setValue(50);
            model.setExtent(1);
            vsb.setEnabled(true);
          }
          final JScrollPane hsp =
              new JScrollPane(
                  ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
                  ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
          {
            final JScrollBar hsb = hsp.getHorizontalScrollBar();
            hsb.setPreferredSize(sbDim);
            final BoundedRangeModel model = hsb.getModel();
            model.setMinimum(0);
            model.setMaximum(100);
            model.setValue(50);
            model.setExtent(1);
            hsb.setEnabled(true);
          }
          final JSplitPane horizontalSplitPane =
              new JSplitPane(
                  JSplitPane.HORIZONTAL_SPLIT, true, twoCanvas ? glCanvas2 : vsp, glCanvas1);
          horizontalSplitPane.setResizeWeight(0.5);
          final JSplitPane verticalSplitPane =
              new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, horizontalSplitPane, hsp);
          verticalSplitPane.setResizeWeight(0.5);
          framePane.add(verticalSplitPane);
        }
        break;
    }
    final GearsES2 demo1 = new GearsES2(swapInterval);
    glCanvas1.addGLEventListener(demo1);
    if (twoCanvas) {
      final RedSquareES2 demo2 = new RedSquareES2(swapInterval);
      glCanvas2.addGLEventListener(demo2);
    }

    final Animator animator = new Animator();
    animator.add(glCanvas1);
    if (twoCanvas) {
      animator.add(glCanvas2);
    }
    final QuitAdapter quitAdapter = new QuitAdapter();
    new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter), glCanvas1).addTo(frame);

    javax.swing.SwingUtilities.invokeAndWait(
        new Runnable() {
          public void run() {
            if (resizeByComp) {
              frame.pack();
            } else {
              setFrameSize(frame, true, frameDim);
            }
            frame.setVisible(true);
          }
        });
    Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true));
    Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas1, true));
    if (twoCanvas) {
      Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glCanvas2, true));
    }

    animator.start();
    Assert.assertTrue(animator.isStarted());
    Assert.assertTrue(animator.isAnimating());

    System.err.println(
        "canvas1 pos/siz: "
            + glCanvas1.getX()
            + "/"
            + glCanvas1.getY()
            + " "
            + glCanvas1.getSurfaceWidth()
            + "x"
            + glCanvas1.getSurfaceHeight());
    if (twoCanvas) {
      System.err.println(
          "canvas2 pos/siz: "
              + glCanvas2.getX()
              + "/"
              + glCanvas2.getY()
              + " "
              + glCanvas2.getSurfaceWidth()
              + "x"
              + glCanvas2.getSurfaceHeight());
    }

    Thread.sleep(Math.max(1000, duration / 2));
    if (null != rwsize) {
      final Dimension compRSizeHalf = new Dimension(rwsize.width / 2, rwsize.height);
      final Dimension frameRSizeHalf =
          new Dimension(twoCanvas ? rwsize.width + 64 : rwsize.width / 2 + 64, rwsize.height + 64);
      if (resizeByComp) {
        setComponentSize(frame, glCanvas1, compRSizeHalf, glCanvas2, compRSizeHalf);
      } else {
        setFrameSize(frame, true, frameRSizeHalf);
      }
      System.err.println(
          "resize canvas1 pos/siz: "
              + glCanvas1.getX()
              + "/"
              + glCanvas1.getY()
              + " "
              + glCanvas1.getSurfaceWidth()
              + "x"
              + glCanvas1.getSurfaceHeight());
      if (twoCanvas) {
        System.err.println(
            "resize canvas2 pos/siz: "
                + glCanvas2.getX()
                + "/"
                + glCanvas2.getY()
                + " "
                + glCanvas2.getSurfaceWidth()
                + "x"
                + glCanvas2.getSurfaceHeight());
      }
    }

    final long t0 = System.currentTimeMillis();
    long t1 = t0;
    while (!quitAdapter.shouldQuit() && t1 - t0 < duration) {
      Thread.sleep(100);
      t1 = System.currentTimeMillis();
    }

    Assert.assertNotNull(frame);
    Assert.assertNotNull(glCanvas1);
    if (twoCanvas) {
      Assert.assertNotNull(glCanvas2);
    } else {
      Assert.assertNull(glCanvas2);
    }

    Assert.assertNotNull(animator);
    animator.stop();
    Assert.assertFalse(animator.isAnimating());
    Assert.assertFalse(animator.isStarted());

    javax.swing.SwingUtilities.invokeAndWait(
        new Runnable() {
          public void run() {
            frame.setVisible(false);
          }
        });
    Assert.assertEquals(false, frame.isVisible());
    javax.swing.SwingUtilities.invokeAndWait(
        new Runnable() {
          public void run() {
            frame.remove(glCanvas1);
            if (twoCanvas) {
              frame.remove(glCanvas2);
            }
            frame.dispose();
          }
        });
  }