Why do do I get GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT using JAVAFX versions greater than 12.02

360 Views Asked by At

I have built a LINUX based UBUNTU snap app using BASE20 (i.e. Ubuntu 20.04) as a target OS, and it is in distribution.

That App works perfectly well using OpenJDK 11 through to 15.0.1 on OpenJFX 11 and 12. However if I move to a more recent version of OpenJFX I get the following error for every screen change (a change of scene on a stage) - the screen goes blank and the following error is displayed on the terminal:

Incomplete attachment. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)(FBO - 820)
Error creating framebuffer object with TexID 1).

If I force a screen re-write (e.g. by switching to a terminal window or another app, then back to my app) the screen then displays the expected contents.

This seems to be a bug in successive JAVAFX releases - however it is possible that something is missing in the UBUNTU 20.04 libraries incorporated in the snap. I will post a similar help request on the Snapcraft site, but maybe someone here has bumped into a similar issue and may have some pointers.

My dev environment is IntelliJ Idea using gradle with openJDK 15.

Thanks in advance

Alan

Edit: I have managed to do some tracing of my own code and into the java library source.

The error occurs after last line executed in this method in file Scene.java - one thing - the application does not crash, it runs with a blank white screen until something forces a screen refresh e.g. opening another full screen app, then closing it again - the desired scene then appears!

first line is at line 2578 in Scene.java

//== 
@Override
       public void mouseEvent(EventType<MouseEvent> type, double x, double y, double screenX, double screenY,
                              MouseButton button, boolean popupTrigger, boolean synthesized,
                              boolean shiftDown, boolean controlDown, boolean altDown, boolean metaDown,
                              boolean primaryDown, boolean middleDown, boolean secondaryDown,
                              boolean backDown, boolean forwardDown)
       {
           MouseEvent mouseEvent = new MouseEvent(type, x, y, screenX, screenY, button,
                   0, // click count will be adjusted by clickGenerator later anyway
                   shiftDown, controlDown, altDown, metaDown,
                   primaryDown, middleDown, secondaryDown, backDown, forwardDown,
                   synthesized, popupTrigger, false, null);
           processMouseEvent(mouseEvent);
       }
       
//===========================================================================

Stack prior to error:

//====        
mouseEvent:2591, Scene$ScenePeerListener (javafx.scene)
run:409, GlassViewEventHandler$MouseEventNotification (com.sun.javafx.tk.quantum)
run:299, GlassViewEventHandler$MouseEventNotification (com.sun.javafx.tk.quantum)
doPrivileged:-1, AccessController (java.security)
lambda$handleMouseEvent$2:447, GlassViewEventHandler (com.sun.javafx.tk.quantum)
get:-1, 2067987277 (com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$812)
runWithoutRenderLock:412, QuantumToolkit (com.sun.javafx.tk.quantum)
handleMouseEvent:446, GlassViewEventHandler (com.sun.javafx.tk.quantum)
handleMouseEvent:556, View (com.sun.glass.ui)
notifyMouse:942, View (com.sun.glass.ui)
_runLoop:-1, GtkApplication (com.sun.glass.ui.gtk)
lambda$runLoop$11:277, GtkApplication (com.sun.glass.ui.gtk)
run:-1, 1159114532 (com.sun.glass.ui.gtk.GtkApplication$$Lambda$115)
run:834, Thread (java.lang)

//============================================================================

Application code call stack:

//==
private void setupStage()
    {

        mLastTitle = mPrimaryStage.getTitle();
        mPrimaryStage.setScene(mScene);
        mPrimaryStage.setTitle("PhotoNoteBook" + MyConstants.TMMARK + " Photo Carousel");
        mPrimaryStage.show();
    }
    
//===    

The Above Method is called by:

//==
public PhotoCarousel(ImageContainerCallBack imageContainerCallBack, Stage primaryStage, Scene lastScene, UUID photoNotebookUuid, int imageNumber)
    {
        DEBUG = (MyLogger.getTraceLevel() == MyLogger.TRACELEVELDEBUG);
        MyLogger.Logi(this.getClass(), " - Method: PhotoCarousel",
                "Message: Starting constructor ", "");


        mImageContainerCallback = imageContainerCallBack;
        mPrimaryStage = primaryStage;
        mLastScene = lastScene;
        mPhotoNotebookUuid = photoNotebookUuid;
        mImageNumber = imageNumber;
        mPhotoNotebookDataList = PhotoNotebookDataList.get();

        setUpScene();
        setupStage();
    }
    
//==

NOTE setupscene() in the above method is a method that creates the scene, and works fine in JAVAFX 11.0.2 -> 11.0.5 The Above Method is called by:

//===
   private void openPhotoCarouselButtonClickHandler()
    {
        mOpenPhotoCarouselButton.setStyle("-fx-background-color:MediumSeaGreen");
        if ((mPhotoNotebookUuid != null) && (photosToWorkWith()))
        {

            PhotoCarousel photoCarousel = new PhotoCarousel(this,
                    mPrimaryStage, mScene, mPhotoNotebookUuid, 0);

        }
        resetButtonColours();
    }
  
//===  

the next code fragment is part of a method that creates buttons and places them on a tool bar. the button described in the fragment uses a lambda to set the button setOnAction variable

The Above Method is called by:

//===
                    .
                    .
                    .
        mOpenPhotoCarouselButton = new Button();
        mOpenPhotoCarouselButton.setOnAction(e -> openPhotoCarouselButtonClickHandler());
        mOpenPhotoCarouselButton.setPrefWidth(buttonWidth);
        mOpenPhotoCarouselButton.setText("Photos");

                .
                .
         
//===

my build.gradle

plugins {
    id 'org.openjfx.javafxplugin' version '0.0.9'
}

plugins {
    id 'java'
    id 'application'
    id "org.beryx.jlink" version "2.22.0"
}

repositories {
    mavenCentral()
    jcenter()
    google()
}


jlink {
    options=['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'photonotebook'
    }
}

group 'com.dryjointproductions.photonotebook'
version '1.4.2'



allprojects {
    apply plugin: 'idea'
    idea.module.outputDir file("out/production/classes")
}

allprojects {
    tasks.withType(JavaCompile) {
        options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
        }
    }


    sourceSets {
        main {
            resources {
                srcDirs += sourceSets.main.java.srcDirs + sourceSets.main.resources.srcDirs + 'resources'
                exclude '**/*.java'
            }
        }
    }

    javafx {
        version = "13.0.2"
        modules = ['javafx.controls', 'javafx.graphics', 'javafx.base','javafx.fxml', 'javafx.swing', 'javafx.web' ]
    }

compileJava  {
            sourceCompatibility = 11
        }

plugins.withType(JavaPlugin).configureEach {
    java {
        modularity.inferModulePath = true
    }
}

application {
    setMainModule ('PhotoNoteBook')
     setMainClassName('com.dryjointproductions.photonotebook.PhotoNoteBook')
}

dependencies {
   // implementation 'com.google.code.gson:gson:2.7'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'org.xerial:sqlite-jdbc:3.28.0'
    implementation group: 'javax.activation', name: 'activation', version: '1.1.1'
    implementation group: 'javax.mail', name: 'mail', version: '1.4.7'
    implementation 'com.drewnoakes:metadata-extractor:2.14.0'
    implementation 'net.coobird:thumbnailator:0.4.12'
}

I will try and file a bug report, if I can find out how! In the meantime, if anyone can find an issue with my Java I'd be grateful!

1

There are 1 best solutions below

0
On

I finally got to the bottom of this bug, but only as far as a work-around, so for anyone else who has this problem,this may help.

I ran the app with the following jvm debug options:

 -Djavafx.verbose=true -Djavafx.debug=true -Dprism.verbose=true -Dprism.debug=true -Dquantum.verbose=true -Dquantum.debug=true -Dquantum.pulsedebug=true -Dprism.order=sw 

It was the latter option that exposed an issue, a crash:

PC.removeDirtyScene:  scene: 1596154225 @ (-1,-1)
PC.removeDirtyScene:  scene: 1596154225 @ (-1,-1)
PC.removeDirtyScene:  scene: 1596154225 @ (-1,-1)
PC.removeDirtyScene:  scene: 1596154225 @ (-1,-1)
PC.addDirtyScene: 12225757175188 scene: 1596154225 @ (-1,-1)
QT.postPulse@(12225760218463): TAPN
PC.addDirtyScene: 12225781351419 scene: 1596154225 @ (-1,-1)
PC.addDirtyScene: 12225781509215 scene: 1596154225 @ (-1,-1)
PC.addDirtyScene: 12225782656044 scene: 1596154225 @ (-1,-1)
QT.endPulse: 12225782846730
java.lang.IllegalArgumentException: WIDTH must be positive
    at javafx.graphics/com.sun.pisces.AbstractSurface.<init>(Unknown Source)
    at javafx.graphics/com.sun.pisces.JavaSurface.<init>(Unknown Source)
    at javafx.graphics/com.sun.prism.sw.SWRTTexture.<init>(Unknown Source)
    at javafx.graphics/com.sun.prism.sw.SWResourceFactory.createRTTexture(Unknown Source)
    at javafx.graphics/com.sun.prism.sw.SWResourceFactory.createRTTexture(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.UploadingPainter.run(Unknown Source)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.base/java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.RenderJob.run(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)
QT.postPulse@(12225783499118): TaPN
PC.addDirtyScene: 12225786804608 scene: 1596154225 @ (-1,-1)
QT.endPulse: 12225786976417

This got me thinking.. if I set the width and height of the stage prior to calling stage.show() this may go away, and it did. e.g.

Stage mPrimaryStage ;

ScreenUtils screenUtils = new ScreenUtils();
        double minX = screenUtils.getMinX();
        double minY = screenUtils.getMinY();
        double height = screenUtils.getScreenHeight();
        double width = screenUtils.getScreenWidth();

        mPrimaryStage.setX(minX);
        mPrimaryStage.setY(minY);

        mPrimaryStage.setWidth(width);
        mPrimaryStage.setHeight(height);
        mPrimaryStage.show();

(ScreenUtils is a utility I created to get Screen information)

The errors "Incomplete attachment. (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)(FBO - 820)" and "Error creating framebuffer object with TexID 1)" are no longer reported.

This work-around has been reported to OpenJDK bug reports.

Thanks all

Alan