Skip to content
Permalink
Browse files
8239589: JavaFX UI will not repaint after reconnecting via Remote Des…
…ktop

Reviewed-by: jvos
Backport-of: 73e70fe978dda9fc821061dfc12bfb742dd7dc25
  • Loading branch information
kevinrushforth committed May 10, 2021
1 parent 6ff7384 commit 26b5960b24fa41681a6598bbfed4acaf209e1f03
Showing 47 changed files with 808 additions and 120 deletions.
@@ -128,7 +128,7 @@ static boolean renderEffectForRectangularNode(NGNode node,
static void renderRectInnerShadow(Graphics g, InnerShadow shadow, float alpha,
float rx, float ry, float rw, float rh)
{
if (itex == null) {
if (itex == null || itex.isSurfaceLost()) {
byte[] sdata = new byte[TEX_SIZE * TEX_SIZE];
fillGaussian(sdata, TEX_SIZE, TEX_SIZE/2, shadow.getChoke(), true);
Image img = Image.fromByteAlphaData(sdata, TEX_SIZE, TEX_SIZE);
@@ -242,7 +242,7 @@ static void drawClippedTexture(Graphics g, Texture tex,
static void renderRectDropShadow(Graphics g, DropShadow shadow, float alpha,
float rx, float ry, float rw, float rh)
{
if (dtex == null) {
if (dtex == null || dtex.isSurfaceLost()) {
byte[] sdata = new byte[TEX_SIZE * TEX_SIZE];
fillGaussian(sdata, TEX_SIZE, TEX_SIZE / 2, shadow.getSpread(), false);
//fillTestPattern(sdata, imgsize);
@@ -107,7 +107,7 @@ protected void renderContent(Graphics g) {

private Texture createTexture(Graphics g, RenderData rd) {
ResourceFactory factory = g.getResourceFactory();
if (!factory.isDeviceReady()) {
if (factory.isDisposed()) {
return null;
}
Texture txt = factory.createTexture(PixelFormat.INT_ARGB_PRE,
@@ -55,13 +55,32 @@ public class NGPhongMaterial {
private TextureMap selfIllumMap = new TextureMap(PhongMaterial.MapType.SELF_ILLUM);

Material createMaterial(ResourceFactory f) {

// Check whether the material is valid; dispose and recreate if needed
if (material != null && !material.isValid()) {
disposeMaterial();
}

if (material == null) {
material = f.createPhongMaterial();
}
validate(f);
return material;
}

private void disposeMaterial() {
diffuseColorDirty = true;
specularColorDirty = true;
specularPowerDirty = true;
diffuseMap.setDirty(true);
specularMap.setDirty(true);
bumpMap.setDirty(true);
selfIllumMap.setDirty(true);

material.dispose();
material = null;
}

private void validate(ResourceFactory f) {

if (diffuseColorDirty) {
@@ -75,6 +75,15 @@ private void renderMeshView(Graphics g) {
g.setup3DRendering();

ResourceFactory rf = g.getResourceFactory();
if (rf == null || rf.isDisposed()) {
return;
}

// Check whether the meshView is valid; dispose and recreate if needed
if (meshView != null && !meshView.isValid()) {
meshView.dispose();
meshView = null;
}

if (meshView == null && mesh != null) {
meshView = rf.createMeshView(mesh.createMesh(rf));
@@ -59,6 +59,13 @@ public class NGTriangleMesh {
private int[] faceSmoothingGroupsFromAndLengthIndices = new int[2];

Mesh createMesh(ResourceFactory rf) {

// Check whether the mesh is valid; dispose and recreate if needed
if (mesh != null && !mesh.isValid()) {
mesh.dispose();
mesh = null;
}

if (mesh == null) {
mesh = rf.createMesh();
meshDirty = true;
@@ -70,6 +70,7 @@ final class PresentingPainter extends ViewPainter {
}
if (factory == null || !factory.isDeviceReady()) {
sceneState.getScene().entireSceneNeedsRepaint();
factory = null;
return;
}

@@ -1359,8 +1359,17 @@ public Exception getException() {
public double getHeight() { return image.getHeight(); }
@Override
public void factoryReset() { dispose(); }

@Override
public void factoryReleased() { dispose(); }
public void factoryReleased() {
dispose();

// ResourceFactory is being disposed; clear reference to avoid leak
if (rf != null) {
rf.removeFactoryListener(this);
rf = null;
}
}
}

@Override public ImageLoader loadPlatformImage(Object platformImage) {
@@ -90,6 +90,7 @@ public float getPixelScaleFactorY() {
factory = GraphicsPipeline.getDefaultResourceFactory();
}
if (factory == null || !factory.isDeviceReady()) {
factory = null;
return;
}

@@ -30,5 +30,6 @@
* This class represents base material for retained mode rendering
*/

public interface Material {
public interface Material extends GraphicsResource {
public boolean isValid();
}
@@ -40,4 +40,6 @@ public boolean buildGeometry(boolean userDefinedNormals,
int faceSmoothingGroups[], int[] faceSmoothingGroupsFromAndLengthIndices);

public int getCount();

public boolean isValid();
}
@@ -32,7 +32,7 @@
* This class represents new retained mode rendering object
* it has a { mesh, material, position, lights and other common rendering properties
*/
public interface MeshView {
public interface MeshView extends GraphicsResource {

public final static int CULL_NONE = CullFace.NONE.ordinal();
public final static int CULL_BACK = CullFace.BACK.ordinal();
@@ -51,4 +51,6 @@ public void setPointLight(int index,
float r, float g, float b, float w);

public void render(Graphics g);

public boolean isValid();
}
@@ -32,15 +32,29 @@
public interface ResourceFactory extends GraphicsResource {

/**
* Returns status of this graphics device.
* Returns whether this resource factory has been disposed.
* If this resource factory has been disposed, it is no longer valid and
* will need to be recreated before any new resources can be created.
* Any attempt to create a resource will be ignored and will return null.
*
* @return true if this resource factory has been disposed.
*/
public boolean isDisposed();

/**
* Returns status of this graphics device, possibly reinitializing it.
* If the device is not ready the createRTTexture and
* present operations will fail.
* Creation of shaders and regular textures will succeed and
* return valid resources.
* As long as the device has not been disposed, creation of shaders and
* regular textures will succeed and return valid resources.
* All hardware resources (RenderTargets and SwapChains) have to be recreated
* after a device-lost event notification.
**/

*
* NOTE: since this method can reinitialize the graphics device if it has
* been released, it should only be called at the start of a rendering pass.
*
* @return true if this graphics device is ready for use.
*/
public boolean isDeviceReady();

public TextureResourcePool getTextureResourcePool();
@@ -252,8 +266,6 @@ public Texture createTexture(PixelFormat formatHint, Texture.Usage usageHint,
public Texture getGlyphTexture();
public boolean isSuperShaderAllowed();

public void dispose();

/*
* 3D stuff
*/
@@ -45,6 +45,7 @@

class D3DContext extends BaseShaderContext {

public static final int D3DERR_DEVICEREMOVED = 0x88760870;
public static final int D3DERR_DEVICENOTRESET = 0x88760869;
public static final int D3DERR_DEVICELOST = 0x88760868;
public static final int E_FAIL = 0x80004005;
@@ -129,8 +130,8 @@ boolean isLost() {
*/
static void validate(int res) {
if (PrismSettings.verbose && FAILED(res)) {
System.out.println("D3D hresult failed :" + hResultToString(res));
new Exception("Stack trace").printStackTrace(System.out);
System.err.println("D3D hresult failed :" + hResultToString(res));
new Exception("Stack trace").printStackTrace(System.err);
}
}

@@ -144,10 +145,39 @@ private void setLost() {
/**
* Validates the device, sets the context lost
* status if necessary, and tries to restore the context if needed.
* If the device has been removed, then it reinitializes the device, which
* disposes the existing factories and contexts.
*/
boolean testLostStateAndReset() {
if (isDisposed()) {
return false;
}

int hr = D3DResourceFactory.nTestCooperativeLevel(pContext);

if (PrismSettings.verbose && FAILED(hr)) {
System.err.print("D3DContext::testLostStateAndReset : ");
switch (hr) {
case D3D_OK:
System.err.println("D3D_OK");
break;
case D3DERR_DEVICELOST:
System.err.println("D3DERR_DEVICELOST");
break;
case D3DERR_DEVICEREMOVED:
System.err.println("D3DERR_DEVICEREMOVED");
break;
case D3DERR_DEVICENOTRESET:
System.err.println("D3DERR_DEVICENOTRESET");
break;
case E_FAIL:
System.err.println("E_FAIL");
break;
default:
System.err.println(String.format("Unknown D3D error 0x%x", hr));
}
}

if (hr == D3DERR_DEVICELOST) {
setLost();
}
@@ -169,6 +199,14 @@ boolean testLostStateAndReset() {
}
}

if (hr == D3DERR_DEVICEREMOVED) {
setLost();

// Reinitialize the D3DPipeline. This will dispose and recreate
// the resource factory and context for each adapter.
D3DPipeline.getInstance().reinitialize();
}

return !FAILED(hr);
}

@@ -186,6 +224,14 @@ boolean validatePresent(int res) {
return !FAILED(res);
}

@Override
public void dispose() {
disposeLCDBuffer();
state = null;

super.dispose();
}

/**
* OpenGL projection transform use z-range of [-1, 1] while D3D expects it
* to be [0, 1], so we need to adjust the matrix, see RT-32880.
@@ -203,6 +249,8 @@ private GeneralTransform3D adjustClipSpace(GeneralTransform3D projViewTx) {
@Override
protected State updateRenderTarget(RenderTarget target, NGCamera camera,
boolean depthTest) {
if (checkDisposed()) return null;

long resourceHandle = ((D3DRenderTarget)target).getResourceHandle();
int res = nSetRenderTarget(pContext, resourceHandle, depthTest, target.isMSAA());
validate(res);
@@ -445,6 +493,8 @@ private static native boolean nGetFrameStats(long pContext,
private static native boolean nIsRTTVolatile(long contextHandle);

public boolean isRTTVolatile() {
if (checkDisposed()) return false;

return nIsRTTVolatile(pContext);
}

@@ -456,6 +506,8 @@ public static String hResultToString(long hResult) {
return "D3DERR_DEVICELOST";
case (int)D3DERR_OUTOFVIDEOMEMORY:
return "D3DERR_OUTOFVIDEOMEMORY";
case (int)D3DERR_DEVICEREMOVED:
return "D3DERR_DEVICEREMOVED";
case (int)D3D_OK:
return "D3D_OK";
default:
@@ -465,15 +517,21 @@ public static String hResultToString(long hResult) {

@Override
public void setDeviceParametersFor2D() {
if (checkDisposed()) return;

nSetDeviceParametersFor2D(pContext);
}

@Override
protected void setDeviceParametersFor3D() {
if (checkDisposed()) return;

nSetDeviceParametersFor3D(pContext);
}

long createD3DMesh() {
if (checkDisposed()) return 0;

return nCreateD3DMesh(pContext);
}

@@ -53,6 +53,11 @@ long getNativeHandle() {
return nativeHandle;
}

@Override
public boolean isValid() {
return !context.isDisposed();
}

@Override
public void dispose() {
disposerRecord.dispose();
@@ -36,6 +36,7 @@
class D3DMeshView extends BaseMeshView {

static int count = 0;

private final D3DContext context;
private final long nativeHandle;

@@ -95,6 +96,11 @@ public void render(Graphics g) {
material.unlockTextureMaps();
}

@Override
public boolean isValid() {
return !context.isDisposed();
}

@Override
public void dispose() {
// TODO: 3D - Need a mechanism to "decRefCount" Mesh and Material
@@ -29,14 +29,14 @@
import com.sun.prism.PhongMaterial;
import com.sun.prism.Texture;
import com.sun.prism.TextureMap;
import com.sun.prism.impl.BaseGraphicsResource;
import com.sun.prism.impl.BasePhongMaterial;
import com.sun.prism.impl.Disposer;
import com.sun.javafx.logging.PlatformLogger;

/**
* TODO: 3D - Need documentation
*/
class D3DPhongMaterial extends BaseGraphicsResource implements PhongMaterial {
class D3DPhongMaterial extends BasePhongMaterial implements PhongMaterial {

static int count = 0;

@@ -115,6 +115,11 @@ public void unlockTextureMaps() {
}
}

@Override
public boolean isValid() {
return !context.isDisposed();
}

@Override
public void dispose() {
disposerRecord.dispose();

1 comment on commit 26b5960

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 26b5960 May 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.