Skip to content

Commit

Permalink
Adjust FXHost repaint
Browse files Browse the repository at this point in the history
  • Loading branch information
ezh committed Jun 26, 2014
1 parent b0f493d commit e9b2bc1
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 66 deletions.
142 changes: 77 additions & 65 deletions src/main/scala/org/digimead/digi/lib/jfx4swt/jfx/FXHost7.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,79 +95,94 @@ class FXHost7(adapter: WeakReference[FXAdapter]) extends FXHost(adapter) {
} {
if (rawPixelsBuf == null || scene == null || disposed)
return
// 1. We want empty frame to draw.
val toDraw = adapter.frameEmpty.getAndSet(null)
val toDrawHeight = height
val toDrawWidth = width
if (toDraw != null && pipeLock.tryLock()) {
if (pipeLock.tryLock()) {
// We want empty frame to draw.
val toDraw = adapter.frameEmpty.getAndSet(null)
val toDrawWidth = width
val toDrawHeight = height
try {
if (scene.getPixels(rawPixelsBuf, width, height)) {
if (!oneMoreFramePlease) {
System.arraycopy(rawPixelsBufArray, 0, pipeBuf, 0, rawPixelsBufArray.length)
// IMHO This is the best of the worst
// It is not block event thread while large frame processing ~-20ms
// Future allow reduce process time to 1-5ms vs 15-25ms
Future { // Memory overhead is minimal.
// 2. Convert pixelsBuf to imageData and save it to empty frame.
pipeLock.lock()
try {
destinationPointer = 0
sourcePointer = 0
for (y 0 until toDrawHeight) {
for (x 0 until toDrawWidth) {
dataToConvert = pipeBuf(sourcePointer)
sourcePointer += 1
toDraw(destinationPointer) = (dataToConvert & 0xFF).asInstanceOf[Byte] //dst:blue
destinationPointer += 1
toDraw(destinationPointer) = ((dataToConvert >> 8) & 0xFF).asInstanceOf[Byte] //dst:green
destinationPointer += 1
toDraw(destinationPointer) = ((dataToConvert >> 16) & 0xFF).asInstanceOf[Byte] //dst:green
destinationPointer += 1
toDraw(destinationPointer) = 0 //alpha
destinationPointer += 1
if (!oneMoreFramePlease) {
if (toDraw != null && toDrawWidth > 0 && toDrawHeight > 0) {
if (scene.getPixels(rawPixelsBuf, toDrawWidth, toDrawHeight)) {
System.arraycopy(rawPixelsBufArray, 0, pipeBuf, 0, rawPixelsBufArray.length)
// IMHO This is the best of the worst
// It is not block event thread while large frame processing ~-20ms
// Future allow reduce process time to 1-5ms vs 15-25ms
Future { // Memory overhead is minimal.
// 2. Convert pixelsBuf to imageData and save it to empty frame.
pipeLock.lock()
try {
destinationPointer = 0
sourcePointer = 0
for (y 0 until toDrawHeight) {
for (x 0 until toDrawWidth) {
dataToConvert = pipeBuf(sourcePointer)
sourcePointer += 1
toDraw(destinationPointer) = (dataToConvert & 0xFF).asInstanceOf[Byte] //dst:blue
destinationPointer += 1
toDraw(destinationPointer) = ((dataToConvert >> 8) & 0xFF).asInstanceOf[Byte] //dst:green
destinationPointer += 1
toDraw(destinationPointer) = ((dataToConvert >> 16) & 0xFF).asInstanceOf[Byte] //dst:green
destinationPointer += 1
toDraw(destinationPointer) = 0 //alpha
destinationPointer += 1
}
}
}
if (adapter.frameFull.compareAndSet(null, toDraw)) {
// Full frame are ready for new chunk
adapter.redraw()
} else {
// Fail. Put empty frame back.
adapter.frameEmpty.set(toDraw)
}
} catch {
case e: ArrayIndexOutOfBoundsException
adapter.frameEmpty.set(toDraw)
sceneNeedsRepaint
case e: Throwable
FXHost.log.error("FXHost pipe. " + e.getMessage(), e)
} finally pipeLock.unlock()
if (adapter.frameFull.compareAndSet(null, toDraw)) {
// Full frame are ready for new chunk
adapter.redraw()
} else {
// Fail. Put an empty frame back.
adapter.frameEmpty.set(toDraw)
}
} catch {
case e: ArrayIndexOutOfBoundsException
adapter.frameEmpty.set(toDraw)
sceneNeedsRepaint
case e: Throwable
adapter.frameEmpty.set(toDraw)
FXHost.log.error("FXHost pipe. " + e.getMessage(), e)
} finally pipeLock.unlock()
}
} else {
// Fail. Put an empty frame back.
adapter.frameEmpty.set(toDraw)
}
} else {
oneMoreFramePlease = false
JFX.execAsync { // Required
if (scene != null && stage != null) {
if (width != SWT.DEFAULT && height != SWT.DEFAULT) {
scene.setSize(width, height)
stage.setSize(width, height)
}
if (toDraw != null)
// Ok. But put an empty frame back.
adapter.frameEmpty.set(toDraw)
if (wantRepaint == null) wantRepaint = Future {
// toDraw == null, so adapter.frameEmpty.set(toDraw) isn't required
for (i 1 to 1000 if adapter.frameEmpty.get == null) // 5 msec
Thread.sleep(5) // 200 FPS max
JFX.execAsync {
wantRepaint = null
repaint()
sceneNeedsRepaint
}
}
adapter.frameEmpty.set(toDraw)
}
} else {
// Fail. Put empty frame back.
adapter.frameEmpty.set(toDraw)
oneMoreFramePlease = false
if (toDraw != null)
adapter.frameEmpty.set(toDraw)
JFX.execAsync { // Required
if (scene != null && stage != null) {
if (toDrawWidth > 0 && toDrawHeight > 0) {
scene.setSize(toDrawWidth, toDrawHeight)
stage.setSize(toDrawWidth, toDrawHeight)
}
sceneNeedsRepaint
}
}
}
} catch {
case e: Throwable
if (toDraw != null)
adapter.frameEmpty.set(toDraw)
FXHost.log.error("FXHost pipe. " + e.getMessage(), e)
} finally pipeLock.unlock()
} else if (wantRepaint == null) wantRepaint = Future {
for (i 1 to 1000 if adapter.frameEmpty.get == null) // 5 sec
Thread.sleep(5) // 200 FPS max
JFX.exec {
wantRepaint = null
repaint()
Future { sceneNeedsRepaint }
}
}
}
def requestFocus(): Boolean = if (disposed) false else adapter.get.map(_.requestFocus()).getOrElse(false)
Expand Down Expand Up @@ -240,8 +255,6 @@ class FXHost7(adapter: WeakReference[FXAdapter]) extends FXHost(adapter) {
val scene = this.scene
this.scene = null
scene.setFillPaint(null)
scene.setScene(null)
scene.setRoot(null)
scene.setCamera(null)
scene.setDragStartListener(null)
scene.setTKDragGestureListener(null)
Expand All @@ -259,6 +272,5 @@ class FXHost7(adapter: WeakReference[FXAdapter]) extends FXHost(adapter) {
this.userScene = null
stage.close()
stage.setTKStageListener(null)
JFX.execAsync { Disposable.clean(stage) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class JFaceCanvas7(host: WeakReference[FXHost]) extends JFaceCanvas(host) {
protected def closeExec(onDispose: JFaceCanvas _) = JFX.execAsync {
lock.synchronized {
val embeddedStage = impl_peer
val embeddedScene = getScene().impl_getPeer()
val embeddedScene = Option(getScene()).map(_.impl_getPeer()) getOrElse null
hide()
if (embeddedStage != null) {
embeddedStage.setVisible(false)
Expand Down

0 comments on commit e9b2bc1

Please sign in to comment.