OpenGL Error for ConfigType.BEST

Good evening all jME/android people,
I have found a bug which I think was introduced in the last nightly build… :troll:

When I set the “eglConfigType = ConfigType.BEST;” which is the default anyways everything works perfectly EXCEPT when the screen of the device goes dim / off and when you turn it back on and the game gets focus/unpause, then I get an ugly OpenGL error, which crashes the app.

Here is the screenshot:

And the error is:
[java]
E/com.jme3.app.AndroidHarness(24287): SEVERE Exception thrown in Thread[GLThread 522,5,main]
E/com.jme3.app.AndroidHarness(24287): com.jme3.renderer.RendererException: An OpenGL error has occurred: invalid value
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.android.RendererUtil.checkGLError(RendererUtil.java:49)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.android.OGLESShaderRenderer.updateUniform(OGLESShaderRenderer.java:655)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.android.OGLESShaderRenderer.updateShaderUniforms(OGLESShaderRenderer.java:769)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.android.OGLESShaderRenderer.setShader(OGLESShaderRenderer.java:973)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.material.Material.render(Material.java:1116)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:523)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:322)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:374)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:763)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:719)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:983)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.app.AndroidHarness.update(AndroidHarness.java:467)
E/com.jme3.app.AndroidHarness(24287): at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:349)
E/com.jme3.app.AndroidHarness(24287): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1516)
E/com.jme3.app.AndroidHarness(24287): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)
E/com.jme3.app.AndroidHarness(24287):
D/STATUSBAR-Clock( 2725): onReceive() - ACTION_SCREEN_ON
E/WifiHW ( 2302): ##################### set firmware type 0 #####################

[/java]

Please check it out?
Thanks

Looks like jME3 is not aware that the context has been reset. Does it only happen with ConfigType.BEST?

Hi actually it is happening for the other settings as well.
What might be the problem?

Hi again.
Does anyone have an idea what that does?
[java] renderManager.setForcedRenderState(null);
[/java]

Could this be causing my problem???
It was added in Revision r10630 of the source which was about 2 days ago.

Remy any idea?

This was added to fix an issue with Nifty when the you use it’s new batched renderer, I’m a bit surprised it could cause your issue.
Do you use the batched nifty renderer? (you do if when you initialize your nifty render device the last parameters are atlasHeight and altlasWidth).
If you do , please try with the non batched renderer.
I’ll test tonight on my side.

Nope, I am not using nifty at all.
Ok sorry for that.

This is what I am seeing in my test app. (condensed logcat with some extra logs put in):

When the context is restarted after the config change, shouldn’t there be a reset for Unshaded? I’m not see one. It could be that Unshaded is not being reset which then uses an invalid shader program?

[java]
5-24 12:10:46.797 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/MatDefs/Misc/Unshaded.frag with GLSLLoader
05-24 12:10:46.797 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: Shader[numSources=2, numUniforms=2, shaderSources=[ShaderSource[name=Common/MatDefs/Misc/Unshaded.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Misc/Unshaded.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:46.804 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: created shader program: 70,001
05-24 12:10:46.804 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Misc/Unshaded.vert
05-24 12:10:46.812 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Misc/Unshaded.frag
05-24 12:10:46.812 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE shader link success
05-24 12:10:46.812 5698 5711 D com.jme3.util.NativeObjectManager: FINEST Registered: Shader[numSources=2, numUniforms=2, shaderSources=[ShaderSource[name=Common/MatDefs/Misc/Unshaded.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Misc/Unshaded.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:46.812 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 70,001, loc: 1
05-24 12:10:46.812 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 70,001, loc: 2
05-24 12:10:46.898 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/MatDefs/Misc/Sky.vert with GLSLLoader
05-24 12:10:46.984 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/ShaderLib/Optics.glsllib with GLSLLoader
05-24 12:10:47.015 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/MatDefs/Misc/Sky.frag with GLSLLoader
05-24 12:10:47.015 5698 5711 D com.jme3.util.NativeObjectManager: FINEST Registered: Image[size=256x256, format=RGBA8, id=70001]
05-24 12:10:47.023 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:47.343 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:47.351 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:47.351 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:47.601 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:47.601 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:47.601 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:47.828 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:47.828 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:47.828 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:48.101 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:48.101 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:48.101 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:48.320 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:48.320 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:48.320 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:48.531 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:48.531 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:48.531 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: Shader[numSources=2, numUniforms=5, shaderSources=[ShaderSource[name=Common/MatDefs/Misc/Sky.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Misc/Sky.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:48.531 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: created shader program: 280,004
05-24 12:10:48.531 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Misc/Sky.vert
05-24 12:10:48.531 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Misc/Sky.frag
05-24 12:10:48.539 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE shader link success
05-24 12:10:48.539 5698 5711 D com.jme3.util.NativeObjectManager: FINEST Registered: Shader[numSources=2, numUniforms=5, shaderSources=[ShaderSource[name=Common/MatDefs/Misc/Sky.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Misc/Sky.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:48.539 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 280,004, loc: 1
05-24 12:10:48.539 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 280,004, loc: 2
05-24 12:10:48.539 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 280,004, loc: 4
05-24 12:10:48.539 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 280,004, loc: 5
05-24 12:10:48.539 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 280,004, loc: 3
05-24 12:10:48.601 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/MatDefs/Gui/Gui.vert with GLSLLoader
05-24 12:10:48.648 5698 5711 D com.jme3.asset.AssetManager: FINER Loaded Common/MatDefs/Gui/Gui.frag with GLSLLoader
05-24 12:10:48.648 5698 5711 D com.jme3.util.NativeObjectManager: FINEST Registered: Image[size=256x256, format=RGBA8, id=140002]
05-24 12:10:48.648 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST === Uploading image Image[size=256x256, format=RGBA8, id=140002]. Using BITMAP PATH ===
05-24 12:10:48.648 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed bitmap. Mipmaps are not generated.
05-24 12:10:48.859 5698 5711 D com.jme3.renderer.android.TextureUtil: FINEST - Uploading compressed image to GL, oldSize = 262,144, newSize = 32,768, ratio = 8
05-24 12:10:48.859 5698 5711 D com.jme3.asset.AndroidImageInfo: FINE Bitmap was deleted.
05-24 12:10:48.859 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: Shader[numSources=2, numUniforms=3, shaderSources=[ShaderSource[name=Common/MatDefs/Gui/Gui.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Gui/Gui.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:48.859 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateShaderData: created shader program: 490,007
05-24 12:10:48.859 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Gui/Gui.vert
05-24 12:10:48.859 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE compile success: Common/MatDefs/Gui/Gui.frag
05-24 12:10:48.859 5698 5711 D com.jme3.renderer.android.OGLESShaderRenderer: FINE shader link success
05-24 12:10:48.859 5698 5711 D com.jme3.util.NativeObjectManager: FINEST Registered: Shader[numSources=2, numUniforms=3, shaderSources=[ShaderSource[name=Common/MatDefs/Gui/Gui.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Gui/Gui.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:48.859 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 490,007, loc: 1
05-24 12:10:48.859 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 490,007, loc: 2
05-24 12:10:48.859 5698 5711 I com.jme3.renderer.android.OGLESShaderRenderer: INFO updateUniformLocation shaderId: 490,007, loc: 3
05-24 12:10:52.398 731 31120 D ExtDispService: onRotationChanged - rotation = 1
05-24 12:10:52.398 731 31120 D ExtDispService: onRotationChanged! - LANDSCAPE!!!
05-24 12:10:52.406 159 808 D HWC_HDMI_MOT: IpcCB notifyCallback: UI Orientation state change - rotation = 270
05-24 12:10:52.406 159 808 D ti_hwc : hdmi_callback: UI Rotation = 3
05-24 12:10:52.406 503 503 D OpenGLRenderer: Flushing caches (mode 0)
05-24 12:10:52.437 503 503 I SystemUIService: onConfigurationChanged reached.
05-24 12:10:52.437 503 503 I SystemUIService: isLayoutXLarge = false
05-24 12:10:52.445 717 717 I PortalService: onConfigurationChanged
05-24 12:10:52.461 5698 5698 D com.jme3.app.AndroidHarness: FINE onPause
05-24 12:10:52.461 5698 5698 D com.jme3.app.AndroidHarness: FINE loseFocus
05-24 12:10:52.593 5698 5698 D com.jme3.app.AndroidHarness: FINE pause: AndroidMediaPlayerAudioRenderer
05-24 12:10:52.593 5698 5698 D com.jme3.app.AndroidHarness: FINE onStop
05-24 12:10:52.593 5698 5698 D com.jme3.app.AndroidHarness: FINE onRetainNonConfigurationInstance
05-24 12:10:52.593 5698 5698 D com.jme3.app.AndroidHarness: FINE onDestroy
05-24 12:10:52.593 5698 5698 D com.jme3.app.AndroidHarness: FINE In Config Change, not stopping app.
05-24 12:10:52.617 5698 5698 V AndroidHarness: Removing Handler class: com.jme3.util.AndroidLogHandler
05-24 12:10:52.617 5698 5698 D com.jme3.app.AndroidHarness: FINE onCreate
05-24 12:10:52.625 5698 5698 D com.jme3.app.AndroidHarness: FINE Using Retained App
05-24 12:10:52.625 5698 5698 I com.jme3.system.android.OGLESContext: INFO Settings width: 540, height: 960, minWidth: 0, minHeight: 0
05-24 12:10:53.086 5698 5884 I com.jme3.system.android.OGLESContext: INFO onSurfaceCreated
05-24 12:10:53.093 5698 5884 D com.jme3.util.NativeObjectManager: FINEST Reset: Shader[numSources=2, numUniforms=5, shaderSources=[ShaderSource[name=Common/MatDefs/Misc/Sky.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Misc/Sky.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:53.093 5698 5884 D com.jme3.util.NativeObjectManager: FINEST Reset: Shader[numSources=2, numUniforms=3, shaderSources=[ShaderSource[name=Common/MatDefs/Gui/Gui.vert, defines, type=Vertex, language=GLSL100], ShaderSource[name=Common/MatDefs/Gui/Gui.frag, defines, type=Fragment, language=GLSL100]]]
05-24 12:10:53.101 5698 5884 D com.jme3.system.android.OGLESContext: FINE GL Surface changed, width: 540 height: 960
05-24 12:10:53.187 5698 5884 W dalvikvm: threadid=11: thread exiting with uncaught exception (group=0x40ac6210)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: FATAL EXCEPTION: GLThread 21792
05-24 12:10:53.187 5698 5884 E AndroidRuntime: com.jme3.renderer.RendererException: An OpenGL error has occurred: invalid value
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.android.RendererUtil.checkGLError(RendererUtil.java:49)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.android.OGLESShaderRenderer.updateUniform(OGLESShaderRenderer.java:661)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.android.OGLESShaderRenderer.updateShaderUniforms(OGLESShaderRenderer.java:775)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.android.OGLESShaderRenderer.setShader(OGLESShaderRenderer.java:981)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.material.Material.render(Material.java:1116)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:523)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:322)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:374)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:763)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:719)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:983)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.app.AndroidHarness.update(AndroidHarness.java:517)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:360)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1487)
05-24 12:10:53.187 5698 5884 E AndroidRuntime: at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1241)
05-24 12:10:53.195 374 697 W ActivityManager: Force finishing activity com.interstatewebgroup.quadcopteres/.MainActivity
05-24 12:10:53.234 5698 5698 D com.jme3.app.AndroidHarness: FINE onPause
05-24 12:10:53.234 5698 5698 D com.jme3.app.AndroidHarness: FINE loseFocus
05-24 12:10:53.234 5698 5698 D com.jme3.app.AndroidHarness: FINE pause: AndroidMediaPlayerAudioRenderer
05-24 12:10:53.265 374 448 I InputReader: Reconfiguring input devices. changes=0x00000004
05-24 12:10:53.265 374 448 I InputReader: Device reconfigured: id=2, name=‘atmxt-i2c’, surface size is now 540x960, mode is 1
05-24 12:10:53.343 731 31269 D ExtDispService: onRotationChanged - rotation = 0
05-24 12:10:53.343 731 31269 D ExtDispService: onRotationChanged! - PORTRAIT!!!
[/java]

@ndebruyn
I think we know why this is happening, just need to figure out how we’re going to fix it.

Actually I am not really sure. I see the shaders are getting reset, and then rendering begins again which should re-upload the shaders.

Yeah, that’s the problem, I think. Not all the native objects are getting reset. In the case above, Unshaded doesn’t get reset.

Ok that is good news.
So what can we/I do to to fix the problem?

I have tried this with the lighting material as well. And it is also happening on it.
Maybe something else is wrong.
A week ago it did not happen at all.
I did a nigtly update a few days ago.

@Momoko_Fan, I guess it’s up to you.

What exactly do you mean?
Is this problem inside the core of jme?

Yeah, that’s the problem, I think. Not all the native objects are getting reset. In the case above, Unshaded doesn’t get reset.

Ok, how would I go about doing this?

@ndebruyn said: What exactly do you mean? Is this problem inside the core of jme?
Kirill made a change to be able to dispose of native objects to clean up memory. The change introduce an issue where 2 native objects can have the same ID, and that's causing the crash. He knows why/where/when the issue occur, he just didn't have the time to fix it yet, I guess it's just a matter of few days.

Thanks man, is there not a way that I can fix this on my side of the code or even get into jME to do it.

The reason I am pushing this is because I have a game now in production on the play store and I really do not

want to get bad reviews for it.

Please help or assist me where you can.

@ndebruyn said: Thanks man, is there not a way that I can fix this on my side of the code or even get into jME to do it.

The reason I am pushing this is because I have a game now in production on the play store and I really do not

want to get bad reviews for it.

Please help or assist me where you can.

This is the danger of building from nightly and trying to release a real game that way.

The easiest way around this is to build from source and just locally revert the relevant changes to the native object stuff. The svn revision is not hard to find because there haven’t been many changes lately because we were trying to get the final release ready.

If you are going to release a production game from HEAD then it’s probably better to build from source yourself anyway. Nightlies may be full of problems and if you build from source you can apply one revision at a time. It’s painful (it’s what I do) but it’s the safest way if you must use unreleased code.

Yeah, I won’t make that mistake again.
One have to learn the hard way, right!
So if I build from source/svn, how or where is the jar files I have replace?
thanks

You can grab the may 10th nightly it should have everything you need and the issue was not yet there.
http://jmonkeyengine.com/nightly/jME3_2013-05-10.zip