Search Unity

Gl.IssuePluginEvent in Android Java Plugin?

Discussion in 'Android' started by Radical435, Oct 30, 2014.

  1. Radical435

    Radical435

    Joined:
    Oct 20, 2014
    Posts:
    24
    Hello all -- So, I've gone through the plugin and IssuePluginEvent documentation a few times, as well as searched the forums for information.

    I'm realizing now that there is a hole in my knowledge -- If I call GL.IssuePluginEvent(0), how would unity know where to call UnityRenderEvent(eventId) ?

    Anyway, I have a monobehavior subclass which creates an android java object. I can call back and forth without problem. I am trying to render a SurfaceTexture's GL texture (from a MediaPlayer), to a texture that unity can read. I have had issues where I get a EGL Invalid surface error; I assume because the texture was created on a different thread than it is being accessed from now.

    I would like to trigger a function on the java class on the rendering thread -- GL.IssuePluginEvent doesn't seem to do anything, at least in my implementation.

    How do I make this happen?
     
  2. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    234
    You could let Unity create the texture based on the height and width of the media being played.

    For GL updating the texture, I use:


    Code (CSharp):
    1.  
    2. // clear the error buffer
    3. Logi(data, "flush: ", GLES20.glGetError());
    4.  
    5. GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureID);
    6. Logi(data, "glbind: ", GLES20.glGetError());
    7.  
    8. GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    9. Logi(data, "min: ", GLES20.glGetError());
    10. GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    11. Logi(data, "mag: ", GLES20.glGetError());
    12.  
    13. GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    14. Logi(data, "wrap s: ", GLES20.glGetError());
    15. GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
    16. Logi(data, "wrap t: ", GLES20.glGetError());
    17.  
    18. GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, thumb, 0);              
    19. Logi(data, "native said: ", GLES20.glGetError());
    20.  
    This works very nicely as long as you call it from inside the normal Update cycle.
    http://docs.unity3d.com/Manual/ExecutionOrder.html

    A coroutine with yield return null; is perfect for this if you don't want to add Update.

    The only problem I have yet to solve is synchronization in multi-threaded rendering, the above code does absolutely nothing when running on multi threaded rendering.

    I also posted a question http://answers.unity3d.com/questions/825386/multithreaded-rendering-on-android-breaks-nativete.html
     
  3. Twistplay

    Twistplay

    Joined:
    Dec 6, 2012
    Posts:
    36
    I'd like to know an answer to this too: when using Multi-threaded rendering on Android, how can we get callbacks on the render thread?

    Looking back over old Unity posts the answer tended to be because multi-threaded rendering wasn't then supported on mobile, there was no need to support GL.IssuePluginEvent / __UnityRenderEvent__. Now that MT rendering is working, is there a mechanism to call back into the plugin? Unfortunately without this, it makes things like video texture plugins impossible when multi-threaded rendering is turned on ....

    Currently this page:

    http://docs.unity3d.com/Manual/NativePluginInterface.html

    Says the callbacks are not supported on mobile.
     
  4. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    234
  5. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    The documentation is wrong here. Native rendering plugins are support on iOS and Android as of Unity 4.5. If you download the example plugin you will see it contains a sample for OpenGL ES as well as pre-compiled libraries for both iOS and Android.
     
  6. Twistplay

    Twistplay

    Joined:
    Dec 6, 2012
    Posts:
    36
    bitter is correct, the docs are wong ... I have now successfully got this working. In raw C (Android NDK) my function is:

    extern void UnityRenderEvent(int eventID)
    ...

    Which successfully picks up my events.

    Another gotcha in the documentation, if you want to interoperate with Java: the example JNI_OnLoad function is wrong, as it doesn't return a value. This causes the event not to be picked up as Unity thinks the library failed to load correctly. At the end of JNI_OnLoad I added:

    return JNI_VERSION_1_6;

    .. and my render events were then picked up.


    Adrian
     
    CatalinMustata and umbrahan like this.
  7. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    Nice catch! I'll make sure the documentation is updated with that.

    Thanks
     
  8. Freezy

    Freezy

    Joined:
    Jul 15, 2012
    Posts:
    234
    The issue of 'one funciton to call them all' still remains. How can multiple 3rd party plugins be reliably merged using this method?

    One way could be to expose the single int parameter in the plugin, allowing more meaning and customization.
    But without any enforcement of this design pattern, how can we be sure only the right amount of work is done?

    A single OnLowLevelRender, that is called only on the rendering thread, with a (semi)known and valid state for interacting with native textures would work much more reliably and require less work.
     
  9. sloopidoopi

    sloopidoopi

    Joined:
    Jan 2, 2010
    Posts:
    244
    Hi,
    i also have problems to call a java method with the GL.IssueEvent mechanism. The problem is that i don't know what kind of Intptr i have to use when i want to call a normal java method. All the answers and docs only show it with using native C functions but not what kind of Intptr i have to use when calling a normal java method.
     
    Last edited: Nov 19, 2015
  10. bitter

    bitter

    Unity Technologies

    Joined:
    Jan 11, 2012
    Posts:
    530
    You can't call into java directly, you have to go through a native C plugin.
     
  11. alfa1993

    alfa1993

    Joined:
    Aug 20, 2015
    Posts:
    26
    Any update on providing these interfaces also to java in order to do rendering task here. Having it only in c++ make it very hard
     
    mark-007 likes this.
  12. TheoBerg

    TheoBerg

    Joined:
    Nov 21, 2017
    Posts:
    1
    I agree, if you want to do your rendering tasks in Java it gets trickier. If I understood everything correctly, You would have to use a C++ (Native) callback to call your Java code using JNI. In order to do so, you must initialize your JNI environment (get some global variable in your native (C++) plugin to contain the JVM instance). This initialization can only be done through Java code (https://stackoverflow.com/questions/38862197/getting-valid-jnienv-pointer). Then you can start using JNI code in you C++ (Native) callbacks to do some rendering in Java.

    Its a bit like tinkering if you ask me. I guess deciding to go full C++ on the rendering code when multithread would be the best...

    disclaimer: I haven't tried my solution yet, I am currently working on it. Will come back to you with some results if you want.
     
  13. corin_w

    corin_w

    Joined:
    Mar 29, 2017
    Posts:
    5
    I'm trying to draw a quad to a FBO (with the colour attachment displayed in a raw image in unity) in java, however, whilst I can clear color and that is reflected in unity, I don't seem to be able to draw any geometry. I have verified that the code works if run inside a non unity android app, is there something unity is doing to block rendering in java?
     
    iansp likes this.