Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8036934

FSEM BufferStrategy breaks on Applet launched Frame

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 7u51
    • client-libs
    • 2d
    • x86_64
    • windows_7

      FULL PRODUCT VERSION :
      java version "1.7.0_51"
      Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Graphics Device: Nvidia GeForce GTS 240
      Graphics Driver Version: 332.21
      Using Dual Monitor setup.
      Internet Explorer Version: 9.0.8112.16421

      A DESCRIPTION OF THE PROBLEM :
      When running an applet in Internet Explorer or Applet Viewer and using the default DirectDraw/Direct3D java2D renderer the applet creates a Frame or JFrame. Initial application is a browser based game that renders to a Canvas inside the frame, for testing setup simpler application based on MultiBufferTest example that uses the Frame itself. In both cases rendering continually fails when switched to Full-Screen Exclusive mode.
      No visible exceptions are thrown and the screen merely flickers when the buffers try to switch.
      Debugging revealed that BufferStrategy constantly sets flags contentsLost and contentsRestored after rendering using retrieved Graphics instance. Steps had to be taken to avoid infinite loop scenario as rendering used while loop to try and ensure rendering always happened.
      Switching out of the application (Alt+Tab) seems to suggest that normal rendering resumes while the Frame is minimised. In fact at times a rendered frame actually shows when the application is restored.
      Interestingly FSEM using the same source code with minimal changes runs fine when launched from a Java Application instead of an Applet.
      Behaviour seems similar to this bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=7011935

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Launch an Applet/JApplet (same effect regardless).
      Applet retrieves default GraphicsDevice.
      Applet retrieves default GraphicsConfiguration, creates Frame/JFrame.
      Switch Frame to FSEM.
      Create BufferStrategy for Frame.
      Begin a render loop filling the Frame with a defined colour each loop.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Screen is then filled with Frame displaying different colours each loop (red/blue/green).
      ACTUAL -
      Screen is filled with Frame, often displays black background with smaller white rectangle, flickers between white and black when render is attempted.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.GraphicsDevice;
      import java.awt.GraphicsEnvironment;

      import javax.swing.JApplet;

      public class TestApplet extends JApplet {
          private static final long serialVersionUID = 1L;

          @Override
          public void start() {
      try {
      int numBuffers = 2;

      try {
      String numBuffersParameter = getParameter("numBuffers");
      numBuffers = Integer.parseInt(numBuffersParameter);

      if (numBuffers < 2
      || numBuffers > FullScreenTest.COLORS.length) {
      numBuffers = 2;
      System.err.println("Must specify between 2 and "
      + FullScreenTest.COLORS.length
      + " buffers, defaulting to " + numBuffers + ".");
      }
      } catch (NumberFormatException e) {
      System.out.println("Invalid number format, defaulting to "
      + numBuffers + " buffers.");
      }

      GraphicsDevice device = GraphicsEnvironment
      .getLocalGraphicsEnvironment().getDefaultScreenDevice();
      new FullScreenTest(numBuffers, device);
      } catch (Exception e) {
      e.printStackTrace();
      }
      System.exit(0);
          }
      }

      import java.awt.Color;
      import java.awt.DisplayMode;
      import java.awt.Frame;
      import java.awt.Graphics;
      import java.awt.GraphicsConfiguration;
      import java.awt.GraphicsDevice;
      import java.awt.Rectangle;
      import java.awt.image.BufferStrategy;

      import javax.swing.JFrame;

      public class FullScreenTest {
          private static final int DISPLAY_WIDTH = 640;
          private static final int DISPLAY_HEIGHT = 480;

          public static Color[] COLORS = new Color[] { Color.red, Color.blue,
      Color.green };
          private static DisplayMode[] BEST_DISPLAY_MODES = new DisplayMode[] {
      new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT, 32,
      DisplayMode.REFRESH_RATE_UNKNOWN),
      new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT, 16,
      DisplayMode.REFRESH_RATE_UNKNOWN),
      new DisplayMode(DISPLAY_WIDTH, DISPLAY_HEIGHT, 8,
      DisplayMode.REFRESH_RATE_UNKNOWN) };

          private final int numBuffers;
          private Frame mainFrame;
          private Rectangle bounds;
          private BufferStrategy bufferStrategy;

          public FullScreenTest(int numBuffers, GraphicsDevice device) {
      this.numBuffers = numBuffers;

      try {
      GraphicsConfiguration gc = device.getDefaultConfiguration();
      mainFrame = new JFrame(gc);
      mainFrame.setUndecorated(true);
      mainFrame.setIgnoreRepaint(true);
      mainFrame.setResizable(false);
      device.setFullScreenWindow(mainFrame);
      if (device.isDisplayChangeSupported()) {
      chooseBestDisplayMode(device);
      }
      bounds = mainFrame.getBounds();
      mainFrame.createBufferStrategy(numBuffers);
      bufferStrategy = mainFrame.getBufferStrategy();
      display();
      } catch (Exception e) {
      e.printStackTrace();
      } finally {
      device.setFullScreenWindow(null);
      }
          }

          public void display() {
      for (int count = 0; count < 5; count++) {
      for (int i = 0; i < numBuffers; i++) {
      Graphics g = bufferStrategy.getDrawGraphics();
      if (!bufferStrategy.contentsLost()) {
      g.setColor(COLORS[i]);
      g.fillRect(0, 0, bounds.width, bounds.height);
      bufferStrategy.show();

      if(bufferStrategy.contentsRestored())
      System.out.println("contentsRestored()");
      }
      else
      {
      System.out.println("contentsLost()");
      }

      g.dispose();

      try {
      Thread.sleep(500);
      } catch (InterruptedException e) {
      }
      }
      }
          }

          private static DisplayMode getBestDisplayMode(GraphicsDevice device) {
      for (int x = 0; x < BEST_DISPLAY_MODES.length; x++) {
      DisplayMode[] modes = device.getDisplayModes();
      for (int i = 0; i < modes.length; i++) {
      DisplayMode displayMode = BEST_DISPLAY_MODES[x];

      if (modes[i].getWidth() == displayMode.getWidth()
      && modes[i].getHeight() == displayMode.getHeight()
      && modes[i].getBitDepth() == displayMode.getBitDepth()) {
      return displayMode;
      }
      }
      }
      return null;
          }

          public static void chooseBestDisplayMode(GraphicsDevice device) {
      DisplayMode best = getBestDisplayMode(device);
      if (best != null) {
      device.setDisplayMode(best);
      }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Prefer Chrome or Firefox for browser testing.

      For a Applet Viewer and IE solution disable DirectX pipeline using either:
      -Dsun.java2d.noddraw=true
      or:
      -Dsun.java2d.opengl=true

      Both less than idea solutions for a browser game client.

      Perhaps eventually create standalone Java Application, this FSEM BufferStrategy rendering behaviour seems to affect Applet only.

            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: