Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.sg.prism;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.sg.PGExternalNode;
import com.sun.prism.Graphics;
import com.sun.prism.PixelFormat;
import com.sun.prism.ResourceFactory;
import com.sun.prism.Texture;
import javafx.util.Callback;
import java.nio.Buffer;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
public class NGExternalNode extends NGNode implements PGExternalNode {
private Texture dsttexture;
private BufferData bufferData;
private final AtomicReference renderData = new AtomicReference(null);
private RenderData rd; // last rendered data
private volatile ReentrantLock bufferLock;
@Override
protected void renderContent(Graphics g) {
RenderData curRenderData = renderData.getAndSet(null);
if (curRenderData != null) {
rd = curRenderData;
}
if (rd == null) return;
int x = rd.bdata.srcbounds.x;
int y = rd.bdata.srcbounds.y;
int w = rd.bdata.srcbounds.width;
int h = rd.bdata.srcbounds.height;
if (dsttexture != null) {
dsttexture.lock();
if (dsttexture.isSurfaceLost() ||
(dsttexture.getContentWidth() != rd.bdata.dstwidth) ||
(dsttexture.getContentHeight() != rd.bdata.dstheight))
{
dsttexture.unlock();
dsttexture.dispose();
dsttexture = createTexture(g, rd);
}
} else {
dsttexture = createTexture(g, rd);
}
if (dsttexture == null) {
return;
}
try {
if (curRenderData != null) {
bufferLock.lock();
try {
dsttexture.update(rd.bdata.srcbuffer,
PixelFormat.INT_ARGB_PRE,
x + rd.dirtyRect.x, y + rd.dirtyRect.y, // dst
x + rd.dirtyRect.x, y + rd.dirtyRect.y, // src
rd.dirtyRect.width, rd.dirtyRect.height, // src
rd.bdata.linestride * 4,
false);
} finally {
bufferLock.unlock();
}
if (rd.clearTarget) {
g.clear();
}
}
g.drawTexture(dsttexture,
x, y, x + w, y + h, // dst
x, y, x + w, y + h); // src
} finally {
dsttexture.unlock();
}
}
private Texture createTexture(Graphics g, RenderData rd) {
ResourceFactory factory = g.getResourceFactory();
if (!factory.isDeviceReady()) {
System.err.println("NGExternalNode: graphics device is not ready");
return null;
}
Texture txt = factory.createTexture(PixelFormat.INT_ARGB_PRE,
Texture.Usage.DYNAMIC,
Texture.WrapMode.CLAMP_NOT_NEEDED,
rd.bdata.dstwidth, rd.bdata.dstheight);
if (txt != null) {
txt.contentsUseful();
} else {
System.err.println("NGExternalNode: failed to create a texture");
}
return txt;
}
@Override
public void setLock(ReentrantLock lock) {
this.bufferLock = lock;
}
private static class BufferData {
// the source pixel buffer
final Buffer srcbuffer;
// line stride of the source buffer
final int linestride;
// source image bounds
final Rectangle srcbounds;
// source image buffer size
final int dstwidth;
final int dstheight;
BufferData(Buffer srcbuffer, int linestride,
int x, int y, int width, int height)
{
this.srcbuffer = srcbuffer;
this.linestride = linestride;
this.srcbounds = new Rectangle(x, y, width, height);
this.dstwidth = linestride;
this.dstheight = srcbuffer.capacity() / linestride;
}
BufferData copyWithBounds(int x, int y, int width, int height) {
return new BufferData(this.srcbuffer, this.linestride, x, y, width, height);
}
}
private static class RenderData {
final BufferData bdata;
final Rectangle dirtyRect;
final boolean clearTarget;
RenderData(BufferData bdata,
int dirtyX, int dirtyY, int dirtyWidth, int dirtyHeight,
boolean clearTarget)
{
this.bdata = bdata;
this.dirtyRect = new Rectangle(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
this.clearTarget = clearTarget;
}
RenderData copyAddDirtyRect(int dirtyX, int dirtyY, int dirtyWidth, int dirtyHeight) {
Rectangle r = new Rectangle(dirtyX, dirtyY, dirtyWidth, dirtyHeight);
r.add(this.dirtyRect);
return new RenderData(this.bdata,
r.x, r.y, r.width, r.height,
this.clearTarget);
}
}
@Override
public void setImageBuffer(Buffer buffer,
int x, int y, int width, int height,
int linestride)
{
bufferData = new BufferData(buffer, linestride, x, y, width, height);
renderData.set(new RenderData(bufferData, x, y, width, height, true));
}
@Override
public void setImageBounds(final int x, final int y, final int width, final int height) {
final boolean shrinked = width < bufferData.srcbounds.width ||
height < bufferData.srcbounds.height;
bufferData = bufferData.copyWithBounds(x, y, width, height);
RenderData prev = renderData.get();
boolean clearTarget = (prev != null ? prev.clearTarget : false);
renderData.set(new RenderData(bufferData, x, y, width, height, clearTarget | shrinked));
}
@Override
public void repaintDirtyRegion(final int dirtyX, final int dirtyY,
final int dirtyWidth, final int dirtyHeight)
{
RenderData prev = renderData.get();
if (prev != null) {
renderData.set(prev.copyAddDirtyRect(dirtyX, dirtyY, dirtyWidth, dirtyHeight));
} else {
renderData.set(new RenderData(bufferData, dirtyX, dirtyY, dirtyWidth, dirtyHeight, false));
}
}
@Override
public void markContentDirty() {
visualsChanged();
}
@Override
protected boolean hasOverlappingContents() { return false; }
}