|
@@ -11,9 +11,11 @@ import com.jme3.util.Screenshots;
|
|
import java.awt.AWTException;
|
|
import java.awt.AWTException;
|
|
import java.awt.BufferCapabilities;
|
|
import java.awt.BufferCapabilities;
|
|
import java.awt.Canvas;
|
|
import java.awt.Canvas;
|
|
|
|
+import java.awt.Graphics;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Image;
|
|
import java.awt.Image;
|
|
import java.awt.ImageCapabilities;
|
|
import java.awt.ImageCapabilities;
|
|
|
|
+import java.awt.RenderingHints;
|
|
import java.awt.event.ComponentAdapter;
|
|
import java.awt.event.ComponentAdapter;
|
|
import java.awt.event.ComponentEvent;
|
|
import java.awt.event.ComponentEvent;
|
|
import java.awt.geom.AffineTransform;
|
|
import java.awt.geom.AffineTransform;
|
|
@@ -32,14 +34,16 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
private FrameBuffer fb;
|
|
private FrameBuffer fb;
|
|
private ByteBuffer byteBuf;
|
|
private ByteBuffer byteBuf;
|
|
private IntBuffer intBuf;
|
|
private IntBuffer intBuf;
|
|
- private boolean activeUpdates = true;
|
|
|
|
private RenderManager rm;
|
|
private RenderManager rm;
|
|
|
|
+ private PaintMode paintMode;
|
|
private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
|
|
private ArrayList<ViewPort> viewPorts = new ArrayList<ViewPort>();
|
|
|
|
|
|
// Visibility/drawing vars
|
|
// Visibility/drawing vars
|
|
private BufferStrategy strategy;
|
|
private BufferStrategy strategy;
|
|
private AffineTransformOp transformOp;
|
|
private AffineTransformOp transformOp;
|
|
- private AtomicBoolean visible = new AtomicBoolean(false);
|
|
|
|
|
|
+ private AtomicBoolean hasNativePeer = new AtomicBoolean(false);
|
|
|
|
+ private AtomicBoolean showing = new AtomicBoolean(false);
|
|
|
|
+ private AtomicBoolean repaintRequest = new AtomicBoolean(false);
|
|
|
|
|
|
// Reshape vars
|
|
// Reshape vars
|
|
private int newWidth = 1;
|
|
private int newWidth = 1;
|
|
@@ -47,10 +51,13 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
private AtomicBoolean reshapeNeeded = new AtomicBoolean(false);
|
|
private AtomicBoolean reshapeNeeded = new AtomicBoolean(false);
|
|
private final Object lock = new Object();
|
|
private final Object lock = new Object();
|
|
|
|
|
|
- public AwtPanel(boolean activeUpdates){
|
|
|
|
- this.activeUpdates = activeUpdates;
|
|
|
|
|
|
+ public AwtPanel(PaintMode paintMode){
|
|
|
|
+ this.paintMode = paintMode;
|
|
|
|
+
|
|
|
|
+ if (paintMode == PaintMode.Accelerated){
|
|
|
|
+ setIgnoreRepaint(true);
|
|
|
|
+ }
|
|
|
|
|
|
- setIgnoreRepaint(true);
|
|
|
|
addComponentListener(new ComponentAdapter(){
|
|
addComponentListener(new ComponentAdapter(){
|
|
@Override
|
|
@Override
|
|
public void componentResized(ComponentEvent e) {
|
|
public void componentResized(ComponentEvent e) {
|
|
@@ -73,7 +80,7 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
super.addNotify();
|
|
super.addNotify();
|
|
|
|
|
|
synchronized (lock){
|
|
synchronized (lock){
|
|
- visible.set(true);
|
|
|
|
|
|
+ hasNativePeer.set(true);
|
|
System.out.println("EDT: addNotify");
|
|
System.out.println("EDT: addNotify");
|
|
}
|
|
}
|
|
|
|
|
|
@@ -83,58 +90,102 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
@Override
|
|
@Override
|
|
public void removeNotify(){
|
|
public void removeNotify(){
|
|
synchronized (lock){
|
|
synchronized (lock){
|
|
- visible.set(false);
|
|
|
|
-// strategy.dispose();
|
|
|
|
-// strategy = null;
|
|
|
|
|
|
+ hasNativePeer.set(false);
|
|
System.out.println("EDT: removeNotify");
|
|
System.out.println("EDT: removeNotify");
|
|
}
|
|
}
|
|
|
|
|
|
super.removeNotify();
|
|
super.removeNotify();
|
|
}
|
|
}
|
|
|
|
|
|
- public void drawFrameInThread(){
|
|
|
|
- if (!visible.get()){
|
|
|
|
|
|
+ @Override
|
|
|
|
+ public void paint(Graphics g){
|
|
|
|
+ Graphics2D g2d = (Graphics2D) g;
|
|
|
|
+ synchronized (lock){
|
|
|
|
+ g2d.drawImage(img, transformOp, 0, 0);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public boolean checkVisibilityState(){
|
|
|
|
+ if (!hasNativePeer.get()){
|
|
if (strategy != null){
|
|
if (strategy != null){
|
|
strategy.dispose();
|
|
strategy.dispose();
|
|
strategy = null;
|
|
strategy = null;
|
|
|
|
+ System.out.println("OGL: Not visible. Destroy strategy.");
|
|
}
|
|
}
|
|
- return;
|
|
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (strategy == null || strategy.contentsLost()){
|
|
|
|
- if (strategy != null){
|
|
|
|
- strategy.dispose();
|
|
|
|
- }
|
|
|
|
- try {
|
|
|
|
- createBufferStrategy(1, new BufferCapabilities(new ImageCapabilities(true), new ImageCapabilities(true), BufferCapabilities.FlipContents.UNDEFINED));
|
|
|
|
- } catch (AWTException ex) {
|
|
|
|
- ex.printStackTrace();
|
|
|
|
|
|
+
|
|
|
|
+ boolean currentShowing = isShowing();
|
|
|
|
+ if (showing.getAndSet(currentShowing) != currentShowing){
|
|
|
|
+ if (currentShowing){
|
|
|
|
+ System.out.println("OGL: Enter showing state.");
|
|
|
|
+ }else{
|
|
|
|
+ System.out.println("OGL: Exit showing state.");
|
|
}
|
|
}
|
|
- strategy = getBufferStrategy();
|
|
|
|
- System.out.println("OGL: BufferStrategy lost!");
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- Graphics2D g2d;
|
|
|
|
|
|
+ return currentShowing;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void repaintInThread(){
|
|
|
|
+ // Convert screenshot.
|
|
|
|
+ byteBuf.clear();
|
|
|
|
+ rm.getRenderer().readFrameBuffer(fb, byteBuf);
|
|
|
|
|
|
synchronized (lock){
|
|
synchronized (lock){
|
|
- g2d = (Graphics2D) strategy.getDrawGraphics();
|
|
|
|
|
|
+ // All operations on img must be synchronized
|
|
|
|
+ // as it is accessed from EDT.
|
|
|
|
+ Screenshots.convertScreenShot2(intBuf, img);
|
|
|
|
+ repaint();
|
|
}
|
|
}
|
|
-
|
|
|
|
- g2d.drawImage(img, transformOp, 0, 0);
|
|
|
|
- g2d.dispose();
|
|
|
|
- strategy.show();
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- public boolean isActiveUpdates() {
|
|
|
|
- return activeUpdates;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void setActiveUpdates(boolean activeUpdates) {
|
|
|
|
|
|
+ public void drawFrameInThread(){
|
|
|
|
+ // Convert screenshot.
|
|
|
|
+ byteBuf.clear();
|
|
|
|
+ rm.getRenderer().readFrameBuffer(fb, byteBuf);
|
|
|
|
+ Screenshots.convertScreenShot2(intBuf, img);
|
|
|
|
+
|
|
synchronized (lock){
|
|
synchronized (lock){
|
|
- this.activeUpdates = activeUpdates;
|
|
|
|
|
|
+ // All operations on strategy should be synchronized (?)
|
|
|
|
+ if (strategy == null){
|
|
|
|
+ try {
|
|
|
|
+ createBufferStrategy(1,
|
|
|
|
+ new BufferCapabilities(
|
|
|
|
+ new ImageCapabilities(true),
|
|
|
|
+ new ImageCapabilities(true),
|
|
|
|
+ BufferCapabilities.FlipContents.UNDEFINED)
|
|
|
|
+ );
|
|
|
|
+ } catch (AWTException ex) {
|
|
|
|
+ ex.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ strategy = getBufferStrategy();
|
|
|
|
+ System.out.println("OGL: Visible. Create strategy.");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Draw screenshot.
|
|
|
|
+ do {
|
|
|
|
+ do {
|
|
|
|
+ Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
|
|
|
|
+ if (g2d == null){
|
|
|
|
+ System.out.println("OGL: DrawGraphics was null.");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
|
|
|
|
+ RenderingHints.VALUE_RENDER_SPEED);
|
|
|
|
+
|
|
|
|
+ g2d.drawImage(img, transformOp, 0, 0);
|
|
|
|
+ g2d.dispose();
|
|
|
|
+ strategy.show();
|
|
|
|
+ } while (strategy.contentsRestored());
|
|
|
|
+ } while (strategy.contentsLost());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public boolean isActiveDrawing(){
|
|
|
|
+ return paintMode != PaintMode.OnRequest && showing.get();
|
|
|
|
+ }
|
|
|
|
+
|
|
public void attachTo(ViewPort ... vps){
|
|
public void attachTo(ViewPort ... vps){
|
|
if (viewPorts.size() > 0){
|
|
if (viewPorts.size() > 0){
|
|
for (ViewPort vp : viewPorts){
|
|
for (ViewPort vp : viewPorts){
|
|
@@ -158,14 +209,19 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
private void reshapeInThread(int width, int height) {
|
|
private void reshapeInThread(int width, int height) {
|
|
byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4);
|
|
byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4);
|
|
intBuf = byteBuf.asIntBuffer();
|
|
intBuf = byteBuf.asIntBuffer();
|
|
|
|
+
|
|
fb = new FrameBuffer(width, height, 1);
|
|
fb = new FrameBuffer(width, height, 1);
|
|
fb.setDepthBuffer(Format.Depth);
|
|
fb.setDepthBuffer(Format.Depth);
|
|
fb.setColorBuffer(Format.RGB8);
|
|
fb.setColorBuffer(Format.RGB8);
|
|
|
|
|
|
- img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
|
|
|
+ synchronized (lock){
|
|
|
|
+ img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
|
|
|
+ }
|
|
|
|
+
|
|
// synchronized (lock){
|
|
// synchronized (lock){
|
|
// img = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(width, height);
|
|
// img = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(width, height);
|
|
// }
|
|
// }
|
|
|
|
+
|
|
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
|
|
AffineTransform tx = AffineTransform.getScaleInstance(1, -1);
|
|
tx.translate(0, -img.getHeight());
|
|
tx.translate(0, -img.getHeight());
|
|
transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
|
|
transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
|
|
@@ -173,6 +229,12 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
for (ViewPort vp : viewPorts){
|
|
for (ViewPort vp : viewPorts){
|
|
vp.setOutputFrameBuffer(fb);
|
|
vp.setOutputFrameBuffer(fb);
|
|
vp.getCamera().resize(width, height, true);
|
|
vp.getCamera().resize(width, height, true);
|
|
|
|
+
|
|
|
|
+ // NOTE: Hack alert. This is done ONLY for custom framebuffers.
|
|
|
|
+ // Main framebuffer should use RenderManager.notifyReshape().
|
|
|
|
+ for (SceneProcessor sp : vp.getProcessors()){
|
|
|
|
+ sp.reshape(vp, width, height);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -185,6 +247,12 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
|
|
|
|
public void postQueue(RenderQueue rq) {
|
|
public void postQueue(RenderQueue rq) {
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void invalidate(){
|
|
|
|
+ // For "PaintMode.OnDemand" only.
|
|
|
|
+ repaintRequest.set(true);
|
|
|
|
+ }
|
|
|
|
|
|
public void postFrame(FrameBuffer out) {
|
|
public void postFrame(FrameBuffer out) {
|
|
if (out != fb){
|
|
if (out != fb){
|
|
@@ -193,13 +261,25 @@ public class AwtPanel extends Canvas implements SceneProcessor {
|
|
|
|
|
|
if (reshapeNeeded.getAndSet(false)){
|
|
if (reshapeNeeded.getAndSet(false)){
|
|
reshapeInThread(newWidth, newHeight);
|
|
reshapeInThread(newWidth, newHeight);
|
|
- }else if (activeUpdates){
|
|
|
|
- byteBuf.clear();
|
|
|
|
- rm.getRenderer().readFrameBuffer(fb, byteBuf);
|
|
|
|
- Screenshots.convertScreenShot2(intBuf, img);
|
|
|
|
- drawFrameInThread();
|
|
|
|
|
|
+ }else{
|
|
|
|
+ if (!checkVisibilityState()){
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ switch (paintMode){
|
|
|
|
+ case Accelerated:
|
|
|
|
+ drawFrameInThread();
|
|
|
|
+ break;
|
|
|
|
+ case Repaint:
|
|
|
|
+ repaintInThread();
|
|
|
|
+ break;
|
|
|
|
+ case OnRequest:
|
|
|
|
+ if (repaintRequest.getAndSet(false)){
|
|
|
|
+ repaintInThread();
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
public void reshape(ViewPort vp, int w, int h) {
|
|
public void reshape(ViewPort vp, int w, int h) {
|